1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// *****************************************************************************
/*!
  \file      src/Control/FileConv/CmdLine/Parser.cpp
  \copyright 2012-2015 J. Bakosi,
             2016-2018 Los Alamos National Security, LLC.,
             2019-2021 Triad National Security, LLC.
             All rights reserved. See the LICENSE file for details.
  \brief     FileConv's command line parser
  \details   This file defines the command-line argument parser for the file 
	     converter, FileConv.
*/
// *****************************************************************************

#include "NoWarning/pegtl.hpp"
#include "NoWarning/charm.hpp"

#include "QuinoaConfig.hpp"
#include "Exception.hpp"
#include "Print.hpp"
#include "Keywords.hpp"
#include "FileConv/Types.hpp"
#include "FileConv/CmdLine/Parser.hpp"
#include "FileConv/CmdLine/Grammar.hpp"

namespace tk {
namespace grm {

tk::Print g_print;

} // grm::
} // tk::

using fileconv::CmdLineParser;

CmdLineParser::CmdLineParser( int argc,
                              char** argv,
                              const tk::Print& print,
                              ctr::CmdLine& cmdline ) :
  StringParser( argc, argv )
// *****************************************************************************
//  Contructor: parse the command line for FileConv
//! \param[in] argc Number of C-style character arrays in argv
//! \param[in] argv C-style character array of character arrays
//! \param[in] print Pretty printer
//! \param[inout] cmdline Command-line stack where data is stored from parsing
// *****************************************************************************
{
  // Create CmdLine (a tagged tuple) to store parsed input
  ctr::CmdLine cmd;

  // Reset parser's output stream to that of print's. This is so that mild
  // warnings emitted during parsing can be output using the pretty printer.
  // Usually, errors and warnings are simply accumulated during parsing and
  // printed during diagnostics after the parser has finished. However, in some
  // special cases we can provide a more user-friendly message right during
  // parsing since there is more information available to construct a more
  // sensible message. This is done in e.g., tk::grm::store_option. Resetting
  // the global g_print, to that of passed in as the constructor argument allows
  // not to have to create a new pretty printer, but use the existing one.
  tk::grm::g_print.reset( print.save() );

  // Parse command line string by populating the underlying tagged tuple
  tao::pegtl::memory_input<> in( m_string, "command line" );
  tao::pegtl::parse< cmd::read_string, tk::grm::action >( in, cmd );

  // Echo errors and warnings accumulated during parsing
  diagnostics( print, cmd.get< tag::error >() );

  // Strip command line (and its underlying tagged tuple) from PEGTL instruments
  // and transfer it out
  cmdline = std::move( cmd );

  // If we got here, the parser has succeeded
  print.item("Parsed command line", "success");

  // Print out help on all command-line arguments if the executable was invoked
  // without arguments or the help was requested
  const auto helpcmd = cmdline.get< tag::help >();
  if (argc == 1 || helpcmd) {
    print.help< tk::QUIET >( tk::fileconv_executable(),
                             cmdline.get< tag::cmdinfo >(),
                             "Command-line Parameters:", "-" );
    print.mandatory< tk::QUIET >(
     "The '--" + kw::input().string() + " <filename>' and the "
     "'--" + kw::output().string() + " <filename>' arguments are mandatory." );
    print.usage< tk::QUIET >(
      tk::fileconv_executable(),
      tk::fileconv_executable() + " -" + *kw::input().alias() + " in.root -" +
        *kw::output().alias() + " out.exo",
      "will read data from 'in.root' (in ROOT format) and output it to "
      "out.exo' (in ExodusII format)" );
   }

  // Print out verbose help for a single keyword if requested
  const auto helpkw = cmdline.get< tag::helpkw >();
  if (!helpkw.keyword.empty())
    print.helpkw< tk::QUIET >( tk::fileconv_executable(), helpkw );

  // Print out version information if it was requested
  const auto version = cmdline.get< tag::version >();
  if (version)
    print.version< tk::QUIET >( tk::fileconv_executable(),
                                tk::quinoa_version(),
                                tk::git_commit(),
                                tk::copyright() );

  // Print out license information if it was requested
  const auto license = cmdline.get< tag::license >();
  if (license)
    print.license< tk::QUIET >( tk::fileconv_executable(), tk::license() );

  // Immediately exit if any help was output or was called without any argument
  // or version or license info was requested with zero exit code
  if (argc == 1 || helpcmd || !helpkw.keyword.empty() || version || license)
    CkExit();

  // Make sure mandatory arguments are set
  auto ialias = kw::input().alias();
  auto oalias = kw::output().alias();<--- Variable 'oalias' is assigned a value that is never used.
  ErrChk( !(cmdline.get< tag::io, tag::input >().empty()),
          "Mandatory input file not specified. "
          "Use '--" + kw::input().string() + " <filename>'" +
          ( ialias ? " or '-" + *ialias + " <filename>'" : "" ) + '.' );
  ErrChk( !(cmdline.get< tag::io, tag::output >().empty()),
          "Mandatory output file not specified. "
          "Use '--" + kw::output().string() + " <filename>'" +
          ( oalias ? " or '-" + *oalias + " <filename>'" : "" ) + '.' );
}