// This file is part of the AspectC++ compiler 'ac++'.
// Copyright (C) 1999-2003  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 __include_expander_h__
#define __include_expander_h__

// Visitor, which expands all project-local includes 

#include "Puma/PreVisitor.h"
#include "Puma/BCStack.h"
#include "Puma/Token.h"
#include "Puma/Unit.h"
#include "ACUnit.h"
using namespace Puma;

namespace Puma {
  class CProject;
  class Token;
  class ErrorStream;
} // namespace Puma

class LineDirectiveMgr;

class IncludeExpander : public PreVisitor {

  struct File {
    Unit *_unit;
    Token *_next;
    File (Unit *u = 0) : _unit (u), _next (0) {
      if (_unit)
        _next = (Token*)_unit->first ();
    }
  };

  ErrorStream &_err;
  CProject &_project;
  LineDirectiveMgr &_line_mgr;
  ACUnit _unit;
  BCStack<File> _files;
  int _depth;
  int _ext_depth;
  Unit *_root;
  bool _forced_includes;

  // Go through the nodes of the syntax tree.
  void iterateNodes (PreTree*);
  
  // expand tokens from a unit (write them into the result unit)
  void write (Unit *unit, Token *first, Token *last);

  // write a string into the unit
  void write (const char *str);

  // print the rest of the topmost unit
  void IncludeExpander::finish ();

  // pop elements from the include stack until depth 'up_to'
  void rewind (int up_to);

  // Visiting the parts of the preprocessor syntax tree.
  
  void visitPreIncludeDirective_Pre (PreIncludeDirective*);

public:
    
  IncludeExpander (ErrorStream &err, CProject &project,
		   LineDirectiveMgr &ldm) :
    _err (err), _project (project), _line_mgr (ldm), _unit (err), _root (0) {}
 
  virtual ~IncludeExpander () {}

  void expand (const char *file);
  ACUnit &unit () { return _unit; }
};  	    

#endif // __include_expander_h__
