//  Clint - Source code checker for C++
//  Copyright (C) 2001  David Pashley
//
//  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 "utility.h"
#include <pwd.h>
#include <unistd.h>
#include <dirent.h>
#include <stdexcept>
#include "input.h"
#include "message.h"

namespace clint {
   
   /*! \fn vector<string> get_plugin_list() {{{
    * \brief compiles a list of plugins to load
    */
   void get_plugin_list(std::vector<std::string>& filelist, std::string directory) {
      struct dirent * dir_entry;
      std::string filename;
      DIR *curdir = opendir(directory.c_str());
      if ( curdir != NULL ) {
         while ( ( dir_entry = readdir(curdir) ) ) {
            filename =  dir_entry->d_name;
            filename = directory + "/" + filename;
            if ( std::string::npos != filename.find(".so") ) {
               filelist.push_back(filename);
            }
         }
         closedir(curdir);
      } else {
         // There is something wrong with the directory. Probably
         // doesn't exist
         // Don't need to be so drastic. maybe we should create the
         // directory
         // throw std::invalid_argument("get_plugin_list: something is wrong with the directory " + directory);
      }
      return;
   }

   // }}}
   // string find_home() {{{

   std::string find_home() {
      struct passwd *user_info = getpwuid(getuid());
      if ( user_info == NULL ) { // unlikely, but test for it anyway
         throw std::runtime_error("You don't exist. Go away"); 
      }
      return std::string( user_info->pw_dir );
   }

   //}}}
   // void parse_args(std::deque<std::string> & args) {{{
   //
   // loop through the deque until it is empty, removing one entry per
   // iteration. If the first character is a '-', then we have an
   // option. if it not an option, it must be the file to test. To deal
   // with options we only need to deal with a few cases where they have
   // an additional argument or we need some information from the
   // argument.
   // 
   // TODO deal with -I/dir -DDEFINE and -D DEFINE=bob
   //  Note: we dont deal with multiple files

   void parse_args(std::deque<std::string> & args) {
      args.pop_front(); // remove the program name
      while ( not args.empty() ) {
         std::string cur_arg = args.front();
         if ('-' == cur_arg[0]) {
            if ("-I" == cur_arg) { 
               args.pop_front(); 
               Input::instance()->add_include(args.front());
            } else if ("-D" == cur_arg) { 
               args.pop_front(); 
               Input::instance()->add_define(args.front(), ""); 
            } else if ("-x" == cur_arg) { args.pop_front(); }
            else if ("-o" == cur_arg) { args.pop_front(); }
            else if ("-b" == cur_arg) { args.pop_front(); }
            else if ("-Xlinker" == cur_arg) { args.pop_front(); }
            else if ("-V" == cur_arg) { args.pop_front(); }
            else if ("-idirafter" == cur_arg) { args.pop_front(); }
            else if ("-imacros" == cur_arg) { args.pop_front(); }
            else if ("-include" == cur_arg) { args.pop_front(); }
            else if ("-iwithprefix" == cur_arg) { args.pop_front(); }

         } else {
            Input::instance()->set_input(cur_arg);
         }
         args.pop_front();
      }
   }  

   // }}}
   // void add_message(std::string message, int line = 0, std::string file = "") {{{

   void add_message(std::string message, int line, std::string file) {
      int tmpline;
      std::string tmpfile;
      if (line == 0) {
         tmpline = Input::instance()->line(); 
      } else { 
         tmpline = line;
      }
      if (file == "") {
         tmpfile = Input::instance()->file(); 
      } else { 
         tmpfile = file;
      }
      Message msg(tmpfile, tmpline, message);
      msgs.push_back(msg);
   }

   // }}}
};


syntax highlighted by Code2HTML, v. 0.9.1