Next: Java Output, Previous: Include Files and Callbacks, Up: Making Genparse Files [Contents][Index]
All of our example so far have shown Genparse creating C code. Genparse also supports C++ output. This section examines the difference between C and C++ output and how to interface a program with a command line parsing class created by Genparse.
As with C output, Genparse creates two or three C++ output files: a
header file, a parser class file, and a callback file. We’ll use
mycopy4.gp
as input to create these files. We invoke Genparse as
follows.
genparse -l cpp -o mycopy4_clp mycopy4.gp
The three created files are named, mycopy4_clp.h
,
mycopy4_clp.cc
, and mycopy4_clp_cb.cc
. We’ll walk through
each one in turn.
• Header File: | ||
• Parser File: | ||
• Callback File: | ||
• Main C++ Program: |
Next: Parser File, Previous: C++ Output, Up: C++ Output [Contents][Index]
The code for mycopy4_clp.h
appears below.
/* mycopy4_clp.h */ #ifndef CMDLINE_H #define CMDLINE_H #include <iostream> #include <string> #include "mycopy4.h" /*---------------------------------------------------------------------------- ** ** class Cmdline ** ** command line parser class ** **--------------------------------------------------------------------------*/ class Cmdline { private: /* parameters */ int _i; std::string _o; bool _h; bool _v; /* other stuff to keep track of */ std::string _program_name; int _optind; public: /* constructor and destructor */ Cmdline (int, char **) throw (std::string); ~Cmdline (){} /* usage function */ void usage (int status); /* return next (non-option) parameter */ int next_param () { return _optind; } /* callback functions */ bool my_callback (); bool outfile_cb (); int i () { return _i; } std::string o () { return _o; } bool h () { return _h; } bool v () { return _v; } }; #endif
The header file contains the definition of the command line parser class. The class defines a logical structure that puts different requirements on the main program than when the output code is in C. We summarize the differences between C and C++ output below.
argv[0]
).
optind
variable is stored in a private member
variable, and is accessible through the next_param ()
member
function.
Next: Callback File, Previous: Header File, Up: C++ Output [Contents][Index]
The parser file defines the non-inlined member functions; i.e., the
constructor and the usage function. The code for mycopy4_clp.cc
appears below.
/* mycopy4_clp.cc */ #include <getopt.h> #include <stdlib.h> #include "mycopy4_clp.h" /*---------------------------------------------------------------------------- ** ** Cmdline::Cmdline () ** ** Constructor method. ** **--------------------------------------------------------------------------*/ Cmdline::Cmdline (int argc, char *argv[]) throw (std::string ) { extern char *optarg; extern int optind; int c; static struct option long_options[] = { {"iterations", required_argument, NULL, 'i'}, {"outfile", required_argument, NULL, 'o'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0} }; _program_name += argv[0]; /* default values */ _i = 1; _h = false; _v = false; optind = 0; while ((c = getopt_long (argc, argv, "i:o:hv", long_options, &optind)) != EOF) { switch (c) { case 'i': _i = atoi (optarg); if (_i < 1) { std::string s; s += "parameter range error: i must be >= 1"; throw (s); } if (_i > MAX) { std::string s; s += "parameter range error: i must be <= MAX"; throw (s); } break; case 'o': _o = optarg; if (!outfile_cb ()) this->usage (EXIT_FAILURE); break; case 'h': _h = true; this->usage (EXIT_SUCCESS); break; case 'v': _v = true; break; default: this->usage (EXIT_FAILURE); } } /* while */ _optind = optind; if (!my_callback ()) usage (EXIT_FAILURE); } /*---------------------------------------------------------------------------- ** ** Cmdline::usage () ** ** Print out usage information, then exit. ** **--------------------------------------------------------------------------*/ void Cmdline::usage (int status) { if (status != EXIT_SUCCESS) std::cerr << "Try `" << _program_name << " --help' for more information.\n"; else { std::cout << "\ usage: " << _program_name << " [ -iohv ] file\n\ Print a file for a number of times to stdout.\n\ [ -i ] [ --iterations ] (type=INTEGER, range=1...MAX, default=1)\n\ Number of times to output <file>.\n\ do it like this\n\ [ -o ] [ --outfile ] (type=STRING)\n\ Output file.\n\ [ -h ] [ --help ] (type=FLAG)\n\ Display this help and exit.\n\ [ -v ] [ --version ] (type=FLAG)\n\ Output version information and exit.\n"; } exit (status); }
As can be seen from this example, the C++ parser is very similar to the
C parser we discussed in Parser Files. The main differences are
that all strings are stored in C++ string
format4.
It is important to note that the callback file is actually included into the parser file. This is because callbacks are implemented as member functions of the parser class, and most C++ compilers will not allow splitting a class’s member functions across more than one file. The bottom line of all this is that you don’t have to link in the callback file, just the parser file.
Next: Main C++ Program, Previous: Parser File, Up: C++ Output [Contents][Index]
The callback file defines skeleton callback routines for the user to
fill in. Their syntax is virtually identical to the C output case,
except that their return values are bool
rather than
int
. The code for mycopy4_clp_cb.cc
appears below.
/* mycopy4_clp_cb.cc */ #include "mycopy4_clp.h" /*---------------------------------------------------------------------------- ** ** Cmdline::my_callback () ** ** Global callback. ** **--------------------------------------------------------------------------*/ bool Cmdline::my_callback () { return true; } /*---------------------------------------------------------------------------- ** ** Cmdline::outfile_cb () ** ** Parameter callback. ** **--------------------------------------------------------------------------*/ bool Cmdline::outfile_cb () { return true; }
Previous: Callback File, Up: C++ Output [Contents][Index]
Due to the syntactic differences between C and C++, the C++ main program
must interact with the command line parser class in a different fashion
than in the C case. The code for mycopy4.cc
appears below.
/* mycopy4.cc */ #include <cstdlib> #include <iostream> #include <fstream> #include "mycopy4_clp.h" using namespace std; #define VERSION "3.0" int main (int argc, char *argv[]) { int i; char c; ifstream input_file; ofstream output_file; bool ofile = false, ifile = false; Cmdline cl (argc, argv); if (cl.v ()) { cout << argv[0] << " version " << VERSION << endl; exit (0); } if (!cl.o ().empty ()) { output_file.open (cl.o ().c_str ()); ofile = true; } if (cl.next_param ()) { input_file.open (argv[cl.next_param ()]); ifile = true; } for (i = 0; i < cl.i (); i++) { if (ifile) c = input_file.get (); else cin >> c; while (c != EOF) { if (ofile) output_file.put (c); else cout << c; if (ifile) c = input_file.get (); else cin >> c; } if (ifile) { input_file.clear (); input_file.seekg (0); } } input_file.close (); output_file.close (); return 0; }
Although mycopy4
provide almost identical output and
functionality as that of mycopy3
, it must access all command line
parameters and related information through the command line parser class
interface.
Older C++ compilers may not support built-in strings. If this is a problem, upgrade your compiler! It’s too old anyway.
Previous: Callback File, Up: C++ Output [Contents][Index]