// This code was generated by CLI, a command line interface
// compiler for C++.
//

// Begin prologue.
//
#include <options-parser.hxx>
//
// End prologue.

#include <cxx/parser/options.hxx>

#include <map>
#include <set>
#include <string>
#include <vector>
#include <ostream>
#include <sstream>

namespace cli
{
  template <typename X>
  struct parser
  {
    static void
    parse (X& x, bool& xs, scanner& s)
    {
      std::string o (s.next ());

      if (s.more ())
      {
        std::string v (s.next ());
        std::istringstream is (v);
        if (!(is >> x && is.eof ()))
          throw invalid_value (o, v);
      }
      else
        throw missing_value (o);

      xs = true;
    }
  };

  template <>
  struct parser<bool>
  {
    static void
    parse (bool& x, scanner& s)
    {
      s.next ();
      x = true;
    }
  };

  template <>
  struct parser<std::string>
  {
    static void
    parse (std::string& x, bool& xs, scanner& s)
    {
      const char* o (s.next ());

      if (s.more ())
        x = s.next ();
      else
        throw missing_value (o);

      xs = true;
    }
  };

  template <typename X>
  struct parser<std::vector<X> >
  {
    static void
    parse (std::vector<X>& c, bool& xs, scanner& s)
    {
      X x;
      bool dummy;
      parser<X>::parse (x, dummy, s);
      c.push_back (x);
      xs = true;
    }
  };

  template <typename X>
  struct parser<std::set<X> >
  {
    static void
    parse (std::set<X>& c, bool& xs, scanner& s)
    {
      X x;
      bool dummy;
      parser<X>::parse (x, dummy, s);
      c.insert (x);
      xs = true;
    }
  };

  template <typename K, typename V>
  struct parser<std::map<K, V> >
  {
    static void
    parse (std::map<K, V>& m, bool& xs, scanner& s)
    {
      std::string o (s.next ());

      if (s.more ())
      {
        std::string ov (s.next ());
        std::string::size_type p = ov.find ('=');

        if (p == std::string::npos)
        {
          K k = K ();

          if (!ov.empty ())
          {
            std::istringstream ks (ov);

            if (!(ks >> k && ks.eof ()))
              throw invalid_value (o, ov);
          }

          m[k] = V ();
        }
        else
        {
          K k = K ();
          V v = V ();
          std::string kstr (ov, 0, p);
          std::string vstr (ov, p + 1);

          if (!kstr.empty ())
          {
            std::istringstream ks (kstr);

            if (!(ks >> k && ks.eof ()))
              throw invalid_value (o, ov);
          }

          if (!vstr.empty ())
          {
            std::istringstream vs (vstr);

            if (!(vs >> v && vs.eof ()))
              throw invalid_value (o, ov);
          }

          m[k] = v;
        }
      }
      else
        throw missing_value (o);

      xs = true;
    }
  };

  template <typename X, typename T, T X::*M>
  void
  thunk (X& x, scanner& s)
  {
    parser<T>::parse (x.*M, s);
  }

  template <typename X, typename T, T X::*M, bool X::*S>
  void
  thunk (X& x, scanner& s)
  {
    parser<T>::parse (x.*M, x.*S, s);
  }
}

#include <map>
#include <cstring>

namespace CXX
{
  namespace Parser
  {
    // options
    //

    options::
    options ()
    : type_map_ (),
      type_map_specified_ (false),
      xml_parser_ ("xerces"),
      xml_parser_specified_ (false),
      generate_validation_ (),
      suppress_validation_ (),
      generate_polymorphic_ (),
      generate_noop_impl_ (),
      generate_print_impl_ (),
      generate_test_driver_ (),
      force_overwrite_ (),
      root_element_first_ (),
      root_element_last_ (),
      root_element_ (),
      root_element_specified_ (false),
      skel_type_suffix_ ("_pskel"),
      skel_type_suffix_specified_ (false),
      skel_file_suffix_ ("-pskel"),
      skel_file_suffix_specified_ (false),
      impl_type_suffix_ ("_pimpl"),
      impl_type_suffix_specified_ (false),
      impl_file_suffix_ ("-pimpl"),
      impl_file_suffix_specified_ (false)
    {
    }

    options::
    options (int& argc,
             char** argv,
             bool erase,
             ::cli::unknown_mode opt,
             ::cli::unknown_mode arg)
    : type_map_ (),
      type_map_specified_ (false),
      xml_parser_ ("xerces"),
      xml_parser_specified_ (false),
      generate_validation_ (),
      suppress_validation_ (),
      generate_polymorphic_ (),
      generate_noop_impl_ (),
      generate_print_impl_ (),
      generate_test_driver_ (),
      force_overwrite_ (),
      root_element_first_ (),
      root_element_last_ (),
      root_element_ (),
      root_element_specified_ (false),
      skel_type_suffix_ ("_pskel"),
      skel_type_suffix_specified_ (false),
      skel_file_suffix_ ("-pskel"),
      skel_file_suffix_specified_ (false),
      impl_type_suffix_ ("_pimpl"),
      impl_type_suffix_specified_ (false),
      impl_file_suffix_ ("-pimpl"),
      impl_file_suffix_specified_ (false)
    {
      ::cli::argv_scanner s (argc, argv, erase);
      _parse (s, opt, arg);
    }

    options::
    options (int start,
             int& argc,
             char** argv,
             bool erase,
             ::cli::unknown_mode opt,
             ::cli::unknown_mode arg)
    : type_map_ (),
      type_map_specified_ (false),
      xml_parser_ ("xerces"),
      xml_parser_specified_ (false),
      generate_validation_ (),
      suppress_validation_ (),
      generate_polymorphic_ (),
      generate_noop_impl_ (),
      generate_print_impl_ (),
      generate_test_driver_ (),
      force_overwrite_ (),
      root_element_first_ (),
      root_element_last_ (),
      root_element_ (),
      root_element_specified_ (false),
      skel_type_suffix_ ("_pskel"),
      skel_type_suffix_specified_ (false),
      skel_file_suffix_ ("-pskel"),
      skel_file_suffix_specified_ (false),
      impl_type_suffix_ ("_pimpl"),
      impl_type_suffix_specified_ (false),
      impl_file_suffix_ ("-pimpl"),
      impl_file_suffix_specified_ (false)
    {
      ::cli::argv_scanner s (start, argc, argv, erase);
      _parse (s, opt, arg);
    }

    options::
    options (int& argc,
             char** argv,
             int& end,
             bool erase,
             ::cli::unknown_mode opt,
             ::cli::unknown_mode arg)
    : type_map_ (),
      type_map_specified_ (false),
      xml_parser_ ("xerces"),
      xml_parser_specified_ (false),
      generate_validation_ (),
      suppress_validation_ (),
      generate_polymorphic_ (),
      generate_noop_impl_ (),
      generate_print_impl_ (),
      generate_test_driver_ (),
      force_overwrite_ (),
      root_element_first_ (),
      root_element_last_ (),
      root_element_ (),
      root_element_specified_ (false),
      skel_type_suffix_ ("_pskel"),
      skel_type_suffix_specified_ (false),
      skel_file_suffix_ ("-pskel"),
      skel_file_suffix_specified_ (false),
      impl_type_suffix_ ("_pimpl"),
      impl_type_suffix_specified_ (false),
      impl_file_suffix_ ("-pimpl"),
      impl_file_suffix_specified_ (false)
    {
      ::cli::argv_scanner s (argc, argv, erase);
      _parse (s, opt, arg);
      end = s.end ();
    }

    options::
    options (int start,
             int& argc,
             char** argv,
             int& end,
             bool erase,
             ::cli::unknown_mode opt,
             ::cli::unknown_mode arg)
    : type_map_ (),
      type_map_specified_ (false),
      xml_parser_ ("xerces"),
      xml_parser_specified_ (false),
      generate_validation_ (),
      suppress_validation_ (),
      generate_polymorphic_ (),
      generate_noop_impl_ (),
      generate_print_impl_ (),
      generate_test_driver_ (),
      force_overwrite_ (),
      root_element_first_ (),
      root_element_last_ (),
      root_element_ (),
      root_element_specified_ (false),
      skel_type_suffix_ ("_pskel"),
      skel_type_suffix_specified_ (false),
      skel_file_suffix_ ("-pskel"),
      skel_file_suffix_specified_ (false),
      impl_type_suffix_ ("_pimpl"),
      impl_type_suffix_specified_ (false),
      impl_file_suffix_ ("-pimpl"),
      impl_file_suffix_specified_ (false)
    {
      ::cli::argv_scanner s (start, argc, argv, erase);
      _parse (s, opt, arg);
      end = s.end ();
    }

    options::
    options (::cli::scanner& s,
             ::cli::unknown_mode opt,
             ::cli::unknown_mode arg)
    : type_map_ (),
      type_map_specified_ (false),
      xml_parser_ ("xerces"),
      xml_parser_specified_ (false),
      generate_validation_ (),
      suppress_validation_ (),
      generate_polymorphic_ (),
      generate_noop_impl_ (),
      generate_print_impl_ (),
      generate_test_driver_ (),
      force_overwrite_ (),
      root_element_first_ (),
      root_element_last_ (),
      root_element_ (),
      root_element_specified_ (false),
      skel_type_suffix_ ("_pskel"),
      skel_type_suffix_specified_ (false),
      skel_file_suffix_ ("-pskel"),
      skel_file_suffix_specified_ (false),
      impl_type_suffix_ ("_pimpl"),
      impl_type_suffix_specified_ (false),
      impl_file_suffix_ ("-pimpl"),
      impl_file_suffix_specified_ (false)
    {
      _parse (s, opt, arg);
    }

    void options::
    print_usage (::std::wostream& os)
    {
      os << "--type-map <mapfile>         Read XML Schema to C++ type mapping information" << ::std::endl
         << "                             from <mapfile>." << ::std::endl;

      os << "--xml-parser <parser>        Use <parser> as the underlying XML parser." << ::std::endl;

      os << "--generate-validation        Generate validation code." << ::std::endl;

      os << "--suppress-validation        Suppress the generation of validation code." << ::std::endl;

      os << "--generate-polymorphic       Generate polymorphism-aware code." << ::std::endl;

      os << "--generate-noop-impl         Generate a sample parser implementation that does" << ::std::endl
         << "                             nothing (no operation)." << ::std::endl;

      os << "--generate-print-impl        Generate a sample parser implementation that" << ::std::endl
         << "                             prints the XML data to 'STDOUT'." << ::std::endl;

      os << "--generate-test-driver       Generate a test driver for the sample parser" << ::std::endl
         << "                             implementation." << ::std::endl;

      os << "--force-overwrite            Force overwriting of the existing implementation" << ::std::endl
         << "                             and test driver files." << ::std::endl;

      os << "--root-element-first         Indicate that the first global element is the" << ::std::endl
         << "                             document root." << ::std::endl;

      os << "--root-element-last          Indicate that the last global element is the" << ::std::endl
         << "                             document root." << ::std::endl;

      os << "--root-element <element>     Indicate that <element> is the document root." << ::std::endl;

      os << "--skel-type-suffix <suffix>  Use the provided <suffix> instead of the default" << ::std::endl
         << "                             '_pskel' to construct the names of the generated" << ::std::endl
         << "                             parser skeletons." << ::std::endl;

      os << "--skel-file-suffix <suffix>  Use the provided <suffix> instead of the default" << ::std::endl
         << "                             '-pskel' to construct the names of the generated" << ::std::endl
         << "                             parser skeleton files." << ::std::endl;

      os << "--impl-type-suffix <suffix>  Use the provided <suffix> instead of the default" << ::std::endl
         << "                             '_pimpl' to construct the names of the parser" << ::std::endl
         << "                             implementations for the built-in XML Schema types" << ::std::endl
         << "                             as well as sample parser implementations." << ::std::endl;

      os << "--impl-file-suffix <suffix>  Use the provided <suffix> instead of the default" << ::std::endl
         << "                             '-pimpl' to construct the names of the generated" << ::std::endl
         << "                             sample parser implementation files." << ::std::endl;
    }

    typedef
    std::map<std::string, void (*) (options&, ::cli::scanner&)>
    _cli_options_map;

    static _cli_options_map _cli_options_map_;

    struct _cli_options_map_init
    {
      _cli_options_map_init ()
      {
        _cli_options_map_["--type-map"] = 
        &::cli::thunk< options, NarrowStrings, &options::type_map_,
          &options::type_map_specified_ >;
        _cli_options_map_["--xml-parser"] = 
        &::cli::thunk< options, NarrowString, &options::xml_parser_,
          &options::xml_parser_specified_ >;
        _cli_options_map_["--generate-validation"] = 
        &::cli::thunk< options, bool, &options::generate_validation_ >;
        _cli_options_map_["--suppress-validation"] = 
        &::cli::thunk< options, bool, &options::suppress_validation_ >;
        _cli_options_map_["--generate-polymorphic"] = 
        &::cli::thunk< options, bool, &options::generate_polymorphic_ >;
        _cli_options_map_["--generate-noop-impl"] = 
        &::cli::thunk< options, bool, &options::generate_noop_impl_ >;
        _cli_options_map_["--generate-print-impl"] = 
        &::cli::thunk< options, bool, &options::generate_print_impl_ >;
        _cli_options_map_["--generate-test-driver"] = 
        &::cli::thunk< options, bool, &options::generate_test_driver_ >;
        _cli_options_map_["--force-overwrite"] = 
        &::cli::thunk< options, bool, &options::force_overwrite_ >;
        _cli_options_map_["--root-element-first"] = 
        &::cli::thunk< options, bool, &options::root_element_first_ >;
        _cli_options_map_["--root-element-last"] = 
        &::cli::thunk< options, bool, &options::root_element_last_ >;
        _cli_options_map_["--root-element"] = 
        &::cli::thunk< options, NarrowString, &options::root_element_,
          &options::root_element_specified_ >;
        _cli_options_map_["--skel-type-suffix"] = 
        &::cli::thunk< options, NarrowString, &options::skel_type_suffix_,
          &options::skel_type_suffix_specified_ >;
        _cli_options_map_["--skel-file-suffix"] = 
        &::cli::thunk< options, NarrowString, &options::skel_file_suffix_,
          &options::skel_file_suffix_specified_ >;
        _cli_options_map_["--impl-type-suffix"] = 
        &::cli::thunk< options, NarrowString, &options::impl_type_suffix_,
          &options::impl_type_suffix_specified_ >;
        _cli_options_map_["--impl-file-suffix"] = 
        &::cli::thunk< options, NarrowString, &options::impl_file_suffix_,
          &options::impl_file_suffix_specified_ >;
      }
    };

    static _cli_options_map_init _cli_options_map_init_;

    bool options::
    _parse (const char* o, ::cli::scanner& s)
    {
      _cli_options_map::const_iterator i (_cli_options_map_.find (o));

      if (i != _cli_options_map_.end ())
      {
        (*(i->second)) (*this, s);
        return true;
      }

      // options base
      //
      if (::CXX::options::_parse (o, s))
        return true;

      return false;
    }

    void options::
    _parse (::cli::scanner& s,
            ::cli::unknown_mode opt_mode,
            ::cli::unknown_mode arg_mode)
    {
      bool opt = true;

      while (s.more ())
      {
        const char* o = s.peek ();

        if (std::strcmp (o, "--") == 0)
        {
          s.skip ();
          opt = false;
          continue;
        }

        if (opt && _parse (o, s));
        else if (opt && std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
        {
          switch (opt_mode)
          {
            case ::cli::unknown_mode::skip:
            {
              s.skip ();
              continue;
            }
            case ::cli::unknown_mode::stop:
            {
              break;
            }
            case ::cli::unknown_mode::fail:
            {
              throw ::cli::unknown_option (o);
            }
          }

          break;
        }
        else
        {
          switch (arg_mode)
          {
            case ::cli::unknown_mode::skip:
            {
              s.skip ();
              continue;
            }
            case ::cli::unknown_mode::stop:
            {
              break;
            }
            case ::cli::unknown_mode::fail:
            {
              throw ::cli::unknown_argument (o);
            }
          }

          break;
        }
      }
    }
  }
}

// Begin epilogue.
//
//
// End epilogue.

