// This file is part of the AspectC++ compiler 'ac++'.
// Copyright (C) 1999-2004  The 'ac++' developers (see aspectc.org)
//                                                                
// This program is free software;  you can redistribute it and/or 
// modify it under the terms of the GNU General Public License as 
// published by the Free Software Foundation; either version 2 of 
// the License, or (at your option) any later version.            
//                                                                
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
// GNU General Public License for more details.                   
//                                                                
// You should have received a copy of the GNU General Public      
// License along with this program; if not, write to the Free     
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
// MA  02111-1307  USA                                           

#ifndef __GccDepFile_h__
#define __GccDepFile_h__

#include "Puma/ErrorStream.h"
#include <filesystem>
#include <string>
#include <vector>
#include <tuple>
#include <list>
#include <set>
#include <iostream>

class GccDepFile {

  const std::filesystem::path path_;
  struct Rule {
    std::list<std::string> targets_;
    std::string source_;
    std::set<std::string> deps_;
    std::set<std::string> phony_targets_;
    void clear() {
      targets_.clear();
      source_.clear();
      deps_.clear();
      phony_targets_.clear();
    }
  };
  std::vector<Rule> rules_;
  int translation_units_;
  int aspect_units_;
  bool phony_target_mode_;

public:
  GccDepFile(int translation_units, int aspect_units, bool phony_target_mode) :
    translation_units_(translation_units), aspect_units_(aspect_units),
    phony_target_mode_(phony_target_mode) {}

  // parse a generated dependency, which is provided as a string, and store the rules
  bool parse(Puma::ErrorStream &err, const std::string &content);

  // With '-MF <out>' and multiple translation units only the dependencies of the last
  // translation unit survive. This function mimics this behavior.
  void discard_overwritten_rules();

  // If the dependency of a translation unit from an aspect header has been detected,
  // the header and its dependencies have to be added to the dependencies of the
  // translation unit.
  void merge_aspect_dependencies(const std::string &aspect_header, int into_rule = 0);

  // print stored rules in Makefile format to the specified output stream
  void print(std::ostream &out, bool including_aspects = false);

  // insert the name of the source file and dependency files for a given rule into 'deps'
  void retrieve_dependencies(int rule, std::set<std::string> &deps);

  // insert the name of the source file and dependency files for a given aspect target into 'deps'
  void retrieve_aspect_dependencies(std::string aspect_header, std::set<std::string> &deps);

  // the set of dependencies for a given rule is extended by inserting 'deps'
  void merge_dependencies(int rule_no, const std::set<std::string> &deps, const std::string &source = "");
};

#endif // __GccDepFile_h__
