/***** This code was generated by Yaggo. Do not edit ******/

#ifndef __NUCMER_CMDLINE_HPP__
#define __NUCMER_CMDLINE_HPP__

#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
#include <string.h>
#include <stdexcept>
#include <string>
#include <limits>
#include <vector>
#include <iostream>
#include <sstream>
#include <memory>

class nucmer_cmdline {
 // Boiler plate stuff. Conversion from string to other formats
  static bool adjust_double_si_suffix(double &res, const char *suffix) {
    if(*suffix == '\0')
      return true;
    if(*(suffix + 1) != '\0')
      return false;

    switch(*suffix) {
    case 'a': res *= 1e-18; break;
    case 'f': res *= 1e-15; break;
    case 'p': res *= 1e-12; break;
    case 'n': res *= 1e-9;  break;
    case 'u': res *= 1e-6;  break;
    case 'm': res *= 1e-3;  break;
    case 'k': res *= 1e3;   break;
    case 'M': res *= 1e6;   break;
    case 'G': res *= 1e9;   break;
    case 'T': res *= 1e12;  break;
    case 'P': res *= 1e15;  break;
    case 'E': res *= 1e18;  break;
    default: return false;
    }
    return true;
  }

  static double conv_double(const char *str, ::std::string &err, bool si_suffix) {
    char *endptr = 0;
    errno = 0;
    double res = strtod(str, &endptr);
    if(endptr == str) {
      err.assign("Invalid floating point string");
      return (double)0.0;
    }
    if(errno) {
      err.assign(strerror(errno));
      return (double)0.0;
    }
    bool invalid =
      si_suffix ? !adjust_double_si_suffix(res, endptr) : *endptr != '\0';
    if(invalid) {
      err.assign("Invalid character");
      return (double)0.0;
    }
    return res;
  }

  static int conv_enum(const char* str, ::std::string& err, const char* const strs[]) {
    int res = 0;
    for(const char* const* cstr = strs; *cstr; ++cstr, ++res)
      if(!strcmp(*cstr, str))
        return res;
    err += "Invalid constant '";
    err += str;
    err += "'. Expected one of { ";
    for(const char* const* cstr = strs; *cstr; ++cstr) {
      if(cstr != strs)
        err += ", ";
      err += *cstr;
    }
    err += " }";
    return -1;
  }

  template<typename T>
  static bool adjust_int_si_suffix(T &res, const char *suffix) {
    if(*suffix == '\0')
      return true;
    if(*(suffix + 1) != '\0')
      return false;

    switch(*suffix) {
    case 'k': res *= (T)1000; break;
    case 'M': res *= (T)1000000; break;
    case 'G': res *= (T)1000000000; break;
    case 'T': res *= (T)1000000000000; break;
    case 'P': res *= (T)1000000000000000; break;
    case 'E': res *= (T)1000000000000000000; break;
    default: return false;
    }
    return true;
  }

  template<typename T>
  static T conv_int(const char *str, ::std::string &err, bool si_suffix) {
    char *endptr = 0;
    errno = 0;
    long long int res = strtoll(str, &endptr, 0);
    if(endptr == str) {
      err.assign("Invalid signed int string");
      return (T)0;
    }
    if(errno) {
      err.assign(strerror(errno));
      return (T)0;
    }
    bool invalid =
      si_suffix ? !adjust_int_si_suffix(res, endptr) : *endptr != '\0';
    if(invalid) {
      err.assign("Invalid character");
      return (T)0;
    }
    if(res > ::std::numeric_limits<T>::max() ||
       res < ::std::numeric_limits<T>::min()) {
      err.assign("Value out of range");
      return (T)0;
    }
    return (T)res;
  }

  template<typename T>
  static T conv_uint(const char *str, ::std::string &err, bool si_suffix) {
    char *endptr = 0;
    errno = 0;
    while(isspace(*str)) { ++str; }
    if(*str == '-') {
      err.assign("Negative value");
      return (T)0;
    }
    unsigned long long int res = strtoull(str, &endptr, 0);
    if(endptr == str) {
      err.assign("Invalid unsigned int string");
      return (T)0;
    }
    if(errno) {
      err.assign(strerror(errno));
      return (T)0;
    }
    bool invalid =
      si_suffix ? !adjust_int_si_suffix(res, endptr) : *endptr != '\0';
    if(invalid) {
      err.assign("Invalid character");
      return (T)0;
    }
    if(res > ::std::numeric_limits<T>::max()) {
      err.assign("Value out of range");
      return (T)0;
    }
    return (T)res;
  }

  template<typename T>
  static ::std::string vec_str(const std::vector<T> &vec) {
    ::std::ostringstream os;
    for(typename ::std::vector<T>::const_iterator it = vec.begin();
        it != vec.end(); ++it) {
      if(it != vec.begin())
        os << ",";
      os << *it;
    }
    return os.str();
  }

  class string : public ::std::string {
  public:
    string() : ::std::string() {}
    explicit string(const ::std::string &s) : std::string(s) {}
    explicit string(const char *s) : ::std::string(s) {}
    int as_enum(const char* const strs[]) {
      ::std::string err;
      int res = conv_enum((const char*)this->c_str(), err, strs);
      if(!err.empty())
        throw ::std::runtime_error(err);
      return res;
    }


    uint32_t as_uint32_suffix() const { return as_uint32(true); }
    uint32_t as_uint32(bool si_suffix = false) const {
      ::std::string err;
      uint32_t res = conv_uint<uint32_t>((const char*)this->c_str(), err, si_suffix);
      if(!err.empty()) {
        ::std::string msg("Invalid conversion of '");
        msg += *this;
        msg += "' to uint32_t: ";
        msg += err;
        throw ::std::runtime_error(msg);
      }
      return res;
    }
    uint64_t as_uint64_suffix() const { return as_uint64(true); }
    uint64_t as_uint64(bool si_suffix = false) const {
      ::std::string err;
      uint64_t res = conv_uint<uint64_t>((const char*)this->c_str(), err, si_suffix);
      if(!err.empty()) {
        ::std::string msg("Invalid conversion of '");
        msg += *this;
        msg += "' to uint64_t: ";
        msg += err;
        throw ::std::runtime_error(msg);
      }
      return res;
    }
    int32_t as_int32_suffix() const { return as_int32(true); }
    int32_t as_int32(bool si_suffix = false) const {
      ::std::string err;
      int32_t res = conv_int<int32_t>((const char*)this->c_str(), err, si_suffix);
      if(!err.empty()) {
        ::std::string msg("Invalid conversion of '");
        msg += *this;
        msg += "' to int32_t: ";
        msg += err;
        throw ::std::runtime_error(msg);
      }
      return res;
    }
    int64_t as_int64_suffix() const { return as_int64(true); }
    int64_t as_int64(bool si_suffix = false) const {
      ::std::string err;
      int64_t res = conv_int<int64_t>((const char*)this->c_str(), err, si_suffix);
      if(!err.empty()) {
        ::std::string msg("Invalid conversion of '");
        msg += *this;
        msg += "' to int64_t: ";
        msg += err;
        throw ::std::runtime_error(msg);
      }
      return res;
    }
    int as_int_suffix() const { return as_int(true); }
    int as_int(bool si_suffix = false) const {
      ::std::string err;
      int res = conv_int<int>((const char*)this->c_str(), err, si_suffix);
      if(!err.empty()) {
        ::std::string msg("Invalid conversion of '");
        msg += *this;
        msg += "' to int_t: ";
        msg += err;
        throw ::std::runtime_error(msg);
      }
      return res;
    }
    long as_long_suffix() const { return as_long(true); }
    long as_long(bool si_suffix = false) const {
      ::std::string err;
      long res = conv_int<long>((const char*)this->c_str(), err, si_suffix);
      if(!err.empty()) {
        ::std::string msg("Invalid conversion of '");
        msg += *this;
        msg += "' to long_t: ";
        msg += err;
        throw ::std::runtime_error(msg);
      }
      return res;
    }
    double as_double_suffix() const { return as_double(true); }
    double as_double(bool si_suffix = false) const {
      ::std::string err;
      double res = conv_double((const char*)this->c_str(), err, si_suffix);
      if(!err.empty()) {
        ::std::string msg("Invalid conversion of '");
        msg += *this;
        msg += "' to double_t: ";
        msg += err;
        throw ::std::runtime_error(msg);
      }
      return res;
    }
  };

public:
  bool                           mum_flag;
  bool                           maxmatch_flag;
  uint32_t                       breaklen_arg;
  bool                           breaklen_given;
  uint32_t                       mincluster_arg;
  bool                           mincluster_given;
  uint32_t                       diagdiff_arg;
  bool                           diagdiff_given;
  double                         diagfactor_arg;
  bool                           diagfactor_given;
  bool                           noextend_flag;
  bool                           forward_flag;
  uint32_t                       maxgap_arg;
  bool                           maxgap_given;
  uint32_t                       minmatch_arg;
  bool                           minmatch_given;
  uint32_t                       minalign_arg;
  bool                           minalign_given;
  bool                           nooptimize_flag;
  bool                           reverse_flag;
  bool                           nosimplify_flag;
  string                         prefix_arg;
  bool                           prefix_given;
  const char *                   delta_arg;
  bool                           delta_given;
  const char *                   sam_short_arg;
  bool                           sam_short_given;
  const char *                   sam_long_arg;
  bool                           sam_long_given;
  string                         save_arg;
  bool                           save_given;
  string                         load_arg;
  bool                           load_given;
  uint64_t                       batch_arg;
  bool                           batch_given;
  uint32_t                       threads_arg;
  bool                           threads_given;
  bool                           banded_flag;
  bool                           large_flag;
  bool                           genome_flag;
  uint64_t                       max_chunk_arg;
  bool                           max_chunk_given;
  const char *                   ref_arg;
  ::std::vector<const char *>    qry_arg;
  typedef ::std::vector<const char *>::iterator qry_arg_it;
  typedef ::std::vector<const char *>::const_iterator qry_arg_const_it;

  enum {
    START_OPT = 1000,
    FULL_HELP_OPT,
    MUM_OPT,
    MAXMATCH_OPT,
    NOEXTEND_OPT,
    NOOPTIMIZE_OPT,
    NOSIMPLIFY_OPT,
    DELTA_OPT,
    SAM_SHORT_OPT,
    SAM_LONG_OPT,
    SAVE_OPT,
    LOAD_OPT,
    BATCH_OPT,
    BANDED_OPT,
    LARGE_OPT
  };

  nucmer_cmdline() :
    mum_flag(false),
    maxmatch_flag(false),
    breaklen_arg((uint32_t)200), breaklen_given(false),
    mincluster_arg((uint32_t)65), mincluster_given(false),
    diagdiff_arg((uint32_t)5), diagdiff_given(false),
    diagfactor_arg((double)0.12), diagfactor_given(false),
    noextend_flag(false),
    forward_flag(false),
    maxgap_arg((uint32_t)90), maxgap_given(false),
    minmatch_arg((uint32_t)20), minmatch_given(false),
    minalign_arg((uint32_t)0), minalign_given(false),
    nooptimize_flag(false),
    reverse_flag(false),
    nosimplify_flag(false),
    prefix_arg("out"), prefix_given(false),
    delta_arg(""), delta_given(false),
    sam_short_arg(""), sam_short_given(false),
    sam_long_arg(""), sam_long_given(false),
    save_arg(""), save_given(false),
    load_arg(""), load_given(false),
    batch_arg(0), batch_given(false),
    threads_arg(0), threads_given(false),
    banded_flag(false),
    large_flag(false),
    genome_flag(false),
    max_chunk_arg((uint64_t)50000), max_chunk_given(false),
    ref_arg(""),
    qry_arg()
  { }

  nucmer_cmdline(int argc, char* argv[]) :
    mum_flag(false),
    maxmatch_flag(false),
    breaklen_arg((uint32_t)200), breaklen_given(false),
    mincluster_arg((uint32_t)65), mincluster_given(false),
    diagdiff_arg((uint32_t)5), diagdiff_given(false),
    diagfactor_arg((double)0.12), diagfactor_given(false),
    noextend_flag(false),
    forward_flag(false),
    maxgap_arg((uint32_t)90), maxgap_given(false),
    minmatch_arg((uint32_t)20), minmatch_given(false),
    minalign_arg((uint32_t)0), minalign_given(false),
    nooptimize_flag(false),
    reverse_flag(false),
    nosimplify_flag(false),
    prefix_arg("out"), prefix_given(false),
    delta_arg(""), delta_given(false),
    sam_short_arg(""), sam_short_given(false),
    sam_long_arg(""), sam_long_given(false),
    save_arg(""), save_given(false),
    load_arg(""), load_given(false),
    batch_arg(0), batch_given(false),
    threads_arg(0), threads_given(false),
    banded_flag(false),
    large_flag(false),
    genome_flag(false),
    max_chunk_arg((uint64_t)50000), max_chunk_given(false),
    ref_arg(""),
    qry_arg()
  { parse(argc, argv); }

  void parse(int argc, char* argv[]) {
    static struct option long_options[] = {
      {"mum", 0, 0, MUM_OPT},
      {"maxmatch", 0, 0, MAXMATCH_OPT},
      {"breaklen", 1, 0, 'b'},
      {"mincluster", 1, 0, 'c'},
      {"diagdiff", 1, 0, 'D'},
      {"diagfactor", 1, 0, 'd'},
      {"noextend", 0, 0, NOEXTEND_OPT},
      {"forward", 0, 0, 'f'},
      {"maxgap", 1, 0, 'g'},
      {"minmatch", 1, 0, 'l'},
      {"minalign", 1, 0, 'L'},
      {"nooptimize", 0, 0, NOOPTIMIZE_OPT},
      {"reverse", 0, 0, 'r'},
      {"nosimplify", 0, 0, NOSIMPLIFY_OPT},
      {"prefix", 1, 0, 'p'},
      {"delta", 1, 0, DELTA_OPT},
      {"sam-short", 1, 0, SAM_SHORT_OPT},
      {"sam-long", 1, 0, SAM_LONG_OPT},
      {"save", 1, 0, SAVE_OPT},
      {"load", 1, 0, LOAD_OPT},
      {"batch", 1, 0, BATCH_OPT},
      {"threads", 1, 0, 't'},
      {"banded", 0, 0, BANDED_OPT},
      {"large", 0, 0, LARGE_OPT},
      {"genome", 0, 0, 'G'},
      {"max-chunk", 1, 0, 'M'},
      {"help", 0, 0, 'h'},
      {"full-help", 0, 0, FULL_HELP_OPT},
      {"usage", 0, 0, 'U'},
      {"version", 0, 0, 'V'},
      {0, 0, 0, 0}
    };
    static const char *short_options = "hVUb:c:D:d:fg:l:L:rp:t:GM:";

    ::std::string err;
#define CHECK_ERR(type,val,which) if(!err.empty()) { ::std::cerr << "Invalid " #type " '" << val << "' for [" which "]: " << err << "\n"; exit(1); }
    while(true) {
      int index = -1;
      int c = getopt_long(argc, argv, short_options, long_options, &index);
      if(c == -1) break;
      switch(c) {
      case ':':
        ::std::cerr << "Missing required argument for "
                  << (index == -1 ? ::std::string(1, (char)optopt) : std::string(long_options[index].name))
                  << ::std::endl;
        exit(1);
      case 'h':
        ::std::cout << usage() << "\n\n" << help() << std::endl;
        exit(0);
      case 'U':
        ::std::cout << usage() << "\nUse --help for more information." << std::endl;
        exit(0);
      case 'V':
        print_version();
        exit(0);
      case '?':
        ::std::cerr << "Use --usage or --help for some help\n";
        exit(1);
      case FULL_HELP_OPT:
        ::std::cout << usage() << "\n\n" << help() << "\n\n" << hidden() << std::flush;
        exit(0);
      case MUM_OPT:
        mum_flag = true;
        break;
      case MAXMATCH_OPT:
        maxmatch_flag = true;
        break;
      case 'b':
        breaklen_given = true;
        breaklen_arg = conv_uint<uint32_t>((const char*)optarg, err, false);
        CHECK_ERR(uint32_t, optarg, "-b, --breaklen=uint32")
        break;
      case 'c':
        mincluster_given = true;
        mincluster_arg = conv_uint<uint32_t>((const char*)optarg, err, false);
        CHECK_ERR(uint32_t, optarg, "-c, --mincluster=uint32")
        break;
      case 'D':
        diagdiff_given = true;
        diagdiff_arg = conv_uint<uint32_t>((const char*)optarg, err, false);
        CHECK_ERR(uint32_t, optarg, "-D, --diagdiff=uint32")
        break;
      case 'd':
        diagfactor_given = true;
        diagfactor_arg = conv_double((const char*)optarg, err, false);
        CHECK_ERR(double_t, optarg, "-d, --diagfactor=double")
        break;
      case NOEXTEND_OPT:
        noextend_flag = true;
        break;
      case 'f':
        forward_flag = true;
        break;
      case 'g':
        maxgap_given = true;
        maxgap_arg = conv_uint<uint32_t>((const char*)optarg, err, false);
        CHECK_ERR(uint32_t, optarg, "-g, --maxgap=uint32")
        break;
      case 'l':
        minmatch_given = true;
        minmatch_arg = conv_uint<uint32_t>((const char*)optarg, err, false);
        CHECK_ERR(uint32_t, optarg, "-l, --minmatch=uint32")
        break;
      case 'L':
        minalign_given = true;
        minalign_arg = conv_uint<uint32_t>((const char*)optarg, err, false);
        CHECK_ERR(uint32_t, optarg, "-L, --minalign=uint32")
        break;
      case NOOPTIMIZE_OPT:
        nooptimize_flag = true;
        break;
      case 'r':
        reverse_flag = true;
        break;
      case NOSIMPLIFY_OPT:
        nosimplify_flag = true;
        break;
      case 'p':
        prefix_given = true;
        prefix_arg.assign(optarg);
        break;
      case DELTA_OPT:
        delta_given = true;
        delta_arg = optarg;
        break;
      case SAM_SHORT_OPT:
        sam_short_given = true;
        sam_short_arg = optarg;
        break;
      case SAM_LONG_OPT:
        sam_long_given = true;
        sam_long_arg = optarg;
        break;
      case SAVE_OPT:
        save_given = true;
        save_arg.assign(optarg);
        break;
      case LOAD_OPT:
        load_given = true;
        load_arg.assign(optarg);
        break;
      case BATCH_OPT:
        batch_given = true;
        batch_arg = conv_uint<uint64_t>((const char*)optarg, err, false);
        CHECK_ERR(uint64_t, optarg, "    --batch=BASES")
        break;
      case 't':
        threads_given = true;
        threads_arg = conv_uint<uint32_t>((const char*)optarg, err, false);
        CHECK_ERR(uint32_t, optarg, "-t, --threads=NUM")
        break;
      case BANDED_OPT:
        banded_flag = true;
        break;
      case LARGE_OPT:
        large_flag = true;
        break;
      case 'G':
        genome_flag = true;
        break;
      case 'M':
        max_chunk_given = true;
        max_chunk_arg = conv_uint<uint64_t>((const char*)optarg, err, false);
        CHECK_ERR(uint64_t, optarg, "-M, --max-chunk=MAX")
        break;
      }
    }

    // Check mutually exlusive switches
    if(maxmatch_flag && mum_flag)
      error("Switches [    --maxmatch] and [    --mum] are mutually exclusive");
    if(reverse_flag && forward_flag)
      error("Switches [-r, --reverse] and [-f, --forward] are mutually exclusive");
    if(delta_given && prefix_given)
      error("Switches [    --delta=PATH] and [-p, --prefix=PREFIX] are mutually exclusive");
    if(sam_short_given && prefix_given)
      error("Switches [    --sam-short=PATH] and [-p, --prefix=PREFIX] are mutually exclusive");
    if(sam_short_given && delta_given)
      error("Switches [    --sam-short=PATH] and [    --delta=PATH] are mutually exclusive");
    if(sam_long_given && prefix_given)
      error("Switches [    --sam-long=PATH] and [-p, --prefix=PREFIX] are mutually exclusive");
    if(sam_long_given && delta_given)
      error("Switches [    --sam-long=PATH] and [    --delta=PATH] are mutually exclusive");
    if(sam_long_given && sam_short_given)
      error("Switches [    --sam-long=PATH] and [    --sam-short=PATH] are mutually exclusive");
    if(batch_given && save_given)
      error("Switches [    --batch=BASES] and [    --save=PREFIX] are mutually exclusive");
    if(batch_given && load_given)
      error("Switches [    --batch=BASES] and [    --load=PREFIX] are mutually exclusive");

    // Parse arguments
    if(argc - optind < 1)
      error("Requires at least 1 argument.");
    ref_arg = argv[optind];
    ++optind;
    for( ; optind < argc; ++optind) {
      qry_arg.push_back(argv[optind]);
    }
  }
  static const char * usage() { return "Usage: nucmer [options] ref:path qry:path+"; }
  class error {
    int code_;
    std::ostringstream msg_;

    // Select the correct version (GNU or XSI) version of
    // strerror_r. strerror_ behaves like the GNU version of strerror_r,
    // regardless of which version is provided by the system.
    static const char* strerror__(char* buf, int res) {
      return res != -1 ? buf : "Invalid error";
    }
    static const char* strerror__(char* buf, char* res) {
      return res;
    }
    static const char* strerror_(int err, char* buf, size_t buflen) {
      return strerror__(buf, strerror_r(err, buf, buflen));
    }
    struct no_t { };

  public:
    static no_t no;
    error(int code = EXIT_FAILURE) : code_(code) { }
    explicit error(const char* msg, int code = EXIT_FAILURE) : code_(code)
      { msg_ << msg; }
    error(const std::string& msg, int code = EXIT_FAILURE) : code_(code)
      { msg_ << msg; }
    error& operator<<(no_t) {
      char buf[1024];
      msg_ << ": " << strerror_(errno, buf, sizeof(buf));
      return *this;
    }
    template<typename T>
    error& operator<<(const T& x) { msg_ << x; return (*this); }
    ~error() {
      ::std::cerr << "Error: " << msg_.str() << "\n"
                  << usage() << "\n"
                  << "Use --help for more information"
                  << ::std::endl;
      exit(code_);
    }
  };
  static const char * help() { return
    "nucmer generates nucleotide alignments between two mutli-FASTA input\n" \
    "files. The out.delta output file lists the distance between insertions\n" \
    "and deletions that produce maximal scoring alignments between each\n" \
    "sequence. The show-* utilities know how to read this format.\n" \
    "\n" \
    "By default, nucmer uses anchor matches that are unique in in the\n" \
    "reference but not necessarily unique in the query. See --mum and\n" \
    "--maxmatch for different bevahiors.\n\n"
    "Options (default value in (), *required):\n"
    "     --mum                                Use anchor matches that are unique in both the reference and query (false)\n"
    "     --maxmatch                           Use all anchor matches regardless of their uniqueness (false)\n"
    " -b, --breaklen=uint32                    Set the distance an alignment extension will attempt to extend poor scoring regions before giving up (200)\n"
    " -c, --mincluster=uint32                  Sets the minimum length of a cluster of matches (65)\n"
    " -D, --diagdiff=uint32                    Set the maximum diagonal difference between two adjacent anchors in a cluster (5)\n"
    " -d, --diagfactor=double                  Set the maximum diagonal difference between two adjacent anchors in a cluster as a differential fraction of the gap length (0.12)\n"
    "     --noextend                           Do not perform cluster extension step (false)\n"
    " -f, --forward                            Use only the forward strand of the Query sequences (false)\n"
    " -g, --maxgap=uint32                      Set the maximum gap between two adjacent matches in a cluster (90)\n"
    " -l, --minmatch=uint32                    Set the minimum length of a single exact match (20)\n"
    " -L, --minalign=uint32                    Minimum length of an alignment, after clustering and extension (0)\n"
    "     --nooptimize                         No alignment score optimization, i.e. if an alignment extension reaches the end of a sequence, it will not backtrack to optimize the alignment score and instead terminate the alignment at the end of the sequence (false)\n"
    " -r, --reverse                            Use only the reverse complement of the Query sequences (false)\n"
    "     --nosimplify                         Don't simplify alignments by removing shadowed clusters. Use this option when aligning a sequence to itself to look for repeats (false)\n"
    " -p, --prefix=PREFIX                      Write output to PREFIX.delta (out)\n"
    "     --delta=PATH                         Output delta file to PATH (instead of PREFIX.delta)\n"
    "     --sam-short=PATH                     Output SAM file to PATH, short format\n"
    "     --sam-long=PATH                      Output SAM file to PATH, long format\n"
    "     --save=PREFIX                        Save suffix array to files starting with PREFIX\n"
    "     --load=PREFIX                        Load suffix array from file starting with PREFIX\n"
    "     --batch=BASES                        Proceed by batch of chunks of BASES from the reference\n"
    " -t, --threads=NUM                        Use NUM threads (# of cores)\n"
    " -U, --usage                              Usage\n"
    " -h, --help                               This message\n"
    "     --full-help                          Detailed help\n"
    " -V, --version                            Version";
  }
  static const char* hidden() { return
    "Hidden options:\n"
    "     --banded                             Enforce absolute banding of dynamic programming matrix based on diagdiff parameter (false)\n"
    "     --large                              Force the use of large offsets (false)\n"
    " -G, --genome                             Map genome to genome (long query sequences) (false)\n"
    " -M, --max-chunk=MAX                      Max chunk. Stop adding sequence for a thread if more than MAX already. (50000)\n"
    "";
  }
  void print_version(::std::ostream &os = std::cout) const {
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "0.0.0"
#endif
    os << PACKAGE_VERSION << "\n";
  }
  void dump(::std::ostream &os = std::cout) {
    os << "mum_flag:" << mum_flag << "\n";
    os << "maxmatch_flag:" << maxmatch_flag << "\n";
    os << "breaklen_given:" << breaklen_given << " breaklen_arg:" << breaklen_arg << "\n";
    os << "mincluster_given:" << mincluster_given << " mincluster_arg:" << mincluster_arg << "\n";
    os << "diagdiff_given:" << diagdiff_given << " diagdiff_arg:" << diagdiff_arg << "\n";
    os << "diagfactor_given:" << diagfactor_given << " diagfactor_arg:" << diagfactor_arg << "\n";
    os << "noextend_flag:" << noextend_flag << "\n";
    os << "forward_flag:" << forward_flag << "\n";
    os << "maxgap_given:" << maxgap_given << " maxgap_arg:" << maxgap_arg << "\n";
    os << "minmatch_given:" << minmatch_given << " minmatch_arg:" << minmatch_arg << "\n";
    os << "minalign_given:" << minalign_given << " minalign_arg:" << minalign_arg << "\n";
    os << "nooptimize_flag:" << nooptimize_flag << "\n";
    os << "reverse_flag:" << reverse_flag << "\n";
    os << "nosimplify_flag:" << nosimplify_flag << "\n";
    os << "prefix_given:" << prefix_given << " prefix_arg:" << prefix_arg << "\n";
    os << "delta_given:" << delta_given << " delta_arg:" << delta_arg << "\n";
    os << "sam_short_given:" << sam_short_given << " sam_short_arg:" << sam_short_arg << "\n";
    os << "sam_long_given:" << sam_long_given << " sam_long_arg:" << sam_long_arg << "\n";
    os << "save_given:" << save_given << " save_arg:" << save_arg << "\n";
    os << "load_given:" << load_given << " load_arg:" << load_arg << "\n";
    os << "batch_given:" << batch_given << " batch_arg:" << batch_arg << "\n";
    os << "threads_given:" << threads_given << " threads_arg:" << threads_arg << "\n";
    os << "banded_flag:" << banded_flag << "\n";
    os << "large_flag:" << large_flag << "\n";
    os << "genome_flag:" << genome_flag << "\n";
    os << "max_chunk_given:" << max_chunk_given << " max_chunk_arg:" << max_chunk_arg << "\n";
    os << "ref_arg:" << ref_arg << "\n";
    os << "qry_arg:" << vec_str(qry_arg) << "\n";
  }
};
#endif // __NUCMER_CMDLINE_HPP__"
