// 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                                            

#include "ClangPragmaHandler.h"
#include "ACModel/Utils.h"

using namespace ACBase;

void ClangPragmaHandler::HandlePragma(clang::Preprocessor &PP, clang::PragmaIntroducer Introducer,
                  clang::Token &PragmaTok) {
  // consume all directive tokens
  clang::Token Tok;
  PP.Lex(Tok);
  if (Tok.isNot(clang::tok::identifier)) {
    p1_.err() << sev_error << Tok.getLocation()
      << "#pragma acxx must be followed by a valid identifier" << endMessage;
    return;
  }

  string command = PP.getSpelling(Tok);
  if (command == "affect" || command == "filter") {
    PP.Lex(Tok);
    if (Tok.isNot(clang::tok::string_literal)) {
      p1_.err() << sev_error << Tok.getLocation()
        << "string literal with filename pattern expected after #pragma acxx " << command
        << endMessage;
      return;
    }
    string pattern = PP.getSpelling(Tok);
    pattern = pattern.substr(1, pattern.length() - 2); // discard double quotes
    string regex = filepattern_to_regex(pattern, '^', '$');
    if (regex[0] != '^') {
      p1_.err() << sev_error << Tok.getLocation() << regex << endMessage;
      return;
    }

    PP.Lex(Tok);
    if (Tok.isNot(clang::tok::eod)) {
      p1_.err() << sev_error << Tok.getLocation()
        << "unexpected tokens after #pragma acxx " << command << endMessage;
      while(Tok.isNot(clang::tok::eod))
        PP.Lex(Tok);
      return;
    }

    if (command == "affect") {
      string file = p1_.source_unit(ACToken(Tok)).name();
      if (p1_.config().project().is_aspect_header(file))
        p1_.register_file_affects(file, pattern, regex);
      else
        p1_.err() << sev_error << PragmaTok.getLocation()
          << "#pragma acxx affect only allowed in aspect header" << endMessage;
    }
    else /* if (command == "filter") */ {
      // hand-over the filter pattern as a regular expression string to the phase 1 parser
      p1_.add_advice_filter(pattern, regex);
    }
  }
  else {
    p1_.err() << sev_error << Tok.getLocation()
      << "invalid command string '" << command << "' used in #pragma acxx"
      << endMessage;
    return;
  }
}
