#ifndef __FILE_FLAGMAP_H_SEEN__
#define __FILE_FLAGMAP_H_SEEN__

/*-----------------------------------------------------------------------------
Copyright (C) 2002, 2006, 2009, 2010, 2011, 2012.

A. Ronald Gallant
Post Office Box 659 
Chapel Hill NC 27514 
USA   

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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

-----------------------------------------------------------------------------*/

// For documentation, first read this file then read frontend.cpp.

// This is the header for routines that read flags and file names from 
// the command line and process the files sequentially.  

// Single and multiple letter flags and reading the argument of flags 
// that take an int, double, or char* argument are supported.  

// Grouping of single letter flags, e.g., -ab instead of -a -b 
// or -id 5 6.0 instead of -i 5 -d 6.0, is supported.  If, e.g., 
// the four flags abc, a, b, and c exist, then -abc will be
// interpreted to mean -abc rather than -a -b -c.

// Relevant to the user are the std::map flag, the std::vector file, and
// two functions that the user codes: define_flag and process_filename.

// File frontend.cpp is an annotated example whose main, define_flag,
// and process_filename can be edited to get a working program.

#include "scltypes.h"
#include <string>
#include <map>

namespace flagmap {

 // The following struct contains all information regarding a flag.
 
 struct fval {
 private:
    bool   ok;          // true if explicitly constructed
 public:
    const  char* msg;   // line to be printed by usage_message
    char   arg;         // true if flag expects an argument
    bool   set;         // true if flag was on the command line
    int    i;           // equals integer argument, if any
    double d;           // equals double argument, if any
    char*  s;           // equals string argument, if any
    bool exists() const { return ok; }
    fval()
    : ok(false), msg(), arg('\0'), set(false), i(0), d(0.0), s() { }
    fval(const char* str)
    : ok(true), msg(str), arg('\0'), set(false), i(0), d(0.0), s() { }
    fval(const char* str, char ch) 
    : ok(true), msg(str), arg(ch), set(false), i(0), d(0.0), s() { }
  };

  // The following map has a flag as key and fval as value.

  extern std::map<std::string,fval> flag;

  // Above, flag "abc" is defined by flag["abc"]=fval("message") if flag 
  // "abc" takes no argument and by flag["abc"]=fval("message",ch) if it 
  // does, where ch = 'i', 'd', or 's' for int, double, or char*, respectively.

  // The following function defines flag and is coded by the user.
  // A sample definition is in frontend.cpp.

  extern void define_flag(std::map<std::string,flagmap::fval>& flag);

  // The following is an example of the optional part of define_flag.
  // Its definition is in flagmap.cpp

  extern void optional_part_example(std::map<std::string,flagmap::fval>& flag);

  // The following vector contains filenames read from the command line.

  extern std::vector<std::string> file;

  // The following function is coded by the user and does the actual
  // work of a program that expects either filenames on the command 
  // line or to read from cin.  A sample definition is in frontend.cpp.

  extern std::istream& process_filename(std::istream& fin, 
    std::string progname,
    std::map<std::string,flagmap::fval> flag, 
    std::vector<std::string> file);

  // The following is a example. Its definition is in flagmap.cpp

  extern std::istream& process_filename_example(std::istream& fin, 
    std::string progname,
    std::map<std::string,flagmap::fval> flag, 
    std::vector<std::string> file);
 
  // The following function reads the command line with error checking.

  extern int process_flag(int argc, char** argp, 
    std::string& progname, 
    std::map<std::string,flagmap::fval>& flag,
    std::vector<std::string>& file); 

  // The following function either sequentially binds fin to the 
  // filenames in file and calls process_filename or assigns cin 
  // to fin and calls process_filename.

  extern int process_file(std::string progname, 
    std::map<std::string,flagmap::fval> flag, 
    std::vector<std::string> file); 

  // The following function prints the usage message

  extern std::ostream& usage_message (std::ostream& fout, 
     std::string progname,
     std::map<std::string,flagmap::fval> flag);
} 

#endif
