#include #include #include #include #include #include #include #include #include // Demo has been tested on Windows XP Professional in bash shell // and MinGW compiler, g++; perl 5.8.8 build 822. This file was // compiled by just doing "g++ a.cc". // // Some commands to try out: // // a "normal" usage of this (demo) application // a.exe arg_file = a.args e = \"blah and blee, 'indeed'\" c = 123 // version of the application // a.exe --version // help on using the application (usage information) // a.exe --help // a.exe --usage // version of the perl based parsers (a_cfg.pl and ip_parser.pm) // a.exe -pv // help on using ip_parser.pm // a.exe --HELP // in the following commands, note the right-most argument // a.exe arg_file = a.args e = \"blah and blee, 'indeed'\" c = 123 --version // a.exe arg_file = a.args e = \"blah and blee, 'indeed'\" c = 123 --help // a.exe arg_file = a.args e = \"blah and blee, 'indeed'\" c = 123 --usage // a.exe arg_file = a.args e = \"blah and blee, 'indeed'\" c = 123 -pv // // There are three versions: the version of the applicatino // (below), the verion of the application specific perl script, // a_cfg.pl, and the version of the generic module, ip_parser.pm char *the_version() { return "the_apps_version_is_0123"; } // The data structure related to the arguments The contents of this // data start with default values and end with the parsed values. // The contents are exchanged with the perl scripts via // Convert::Binary::C typedef struct _a_str_ { int a; float b; int c; char d[ 256 ]; char e[ 128 ]; char f[ 128 ]; float g; } a_str; int main( int argc __attribute__ ((unused)), const char **argv __attribute__ ((unused)) ) { std::string a_args; std::string a_io; if( argc == 1 ) { // Just process as per default values // This demo app has nothing to do with default values exit( 0 ); } a_str a; // initialize to default values { a.a = 1; a.b = -2.0; snprintf( a.d, 256, "this is a default string value" ); snprintf( a.e, 128, "a default string 'value' with \"quotes\"" ); snprintf( a.f, 128, "default_symbol" ); a.g = 1.23e-5; // write out default values -- these will be read by // the perl script that parsers this app's arguments FILE *fp; a_io = "a.io"; if( ! ( fp = fopen( a_io.c_str(), "wb") ) ) { printf("Unable to open %s for writing binary stuff\n", a_io.c_str()); exit(-1); } int rc; rc = (int)fwrite( &a, 1, sizeof( a ), fp ); if( rc != (int)sizeof( a ) ) { printf("Wrote %d instead of %d to %s\n", rc, sizeof( a ), a_io.c_str() ); exit(-1); } if( fclose( fp ) ) { printf("Unable to close %s\n", a_io.c_str()); exit(-1); } } // Build up the command used to call the perl script that // parses the arguments. Distinguish between arguments // to this application and arguments to the perl based parser! a_args = "perl a_cfg.pl "; for( int i = 1; i < argc; i++ ) { a_args += ( argv[ i ] ) + (std::string)" "; } // next four args are purely for parsing arguments (menaing, they // are not part of the application as such) // // In case the user wanted to know the version of this // application, ther perl script will provide it to him // by means of argument named app_version a_args += "app_version = " + (std::string) the_version() + " "; // io_file is the file used to exchange data between this C // application the perl script -- this is the file into // which the default arguments have already been written // to in the code block above a_args += "io_file = " + a_io + " "; // ip_str is the name of the data structure that contains // the arguments of this application a_args += "ip_str = a_str "; // h_file is the file that contains the definition of ip_str; // for this demo, it is just this file a_args += "h_file = a.cc "; // use system command to launch the perl script and // get the return code (rc) int rc = system( a_args.c_str() ); // I could not make successful parsing return 0 since // Getopt::Declare returns 0 on encountering the user's request // for usage information! So I made successful parsing // for non-trivial arguments (meaning not requests for help // or for version) return 1 if( rc < 0 ) { printf("Error processing arguments\n"); exit(-1); } if( rc != 1 ) { // user wanted version or usage information // which was provided by the perl script; // and so we are now done return( 0 ); } // rc == 1 is the only case in which the // application continues processing { a.a = 0; a.b = 0.0; a.g = 0.0; // Read in the parsed arguments FILE *fp; a_io = "a.io"; if( ! ( fp = fopen( a_io.c_str(), "rb") ) ) { printf("Unable to open %s for reading binary stuff\n", a_io.c_str()); exit(-1); } int rc; rc = (int)fread( &a, 1, sizeof( a ), fp ); if( rc != (int)sizeof( a ) ) { printf("Wrote %d instead of %d to %s\n", rc, sizeof( a ), a_io.c_str() ); exit(-1); } if( fclose( fp ) ) { printf("Unable to close %s\n", a_io.c_str()); exit(-1); } } // This demo ends by printing the parsed // arguments gotten from the perl script printf("Read values:\n\t\t|a:%d\n\t\t|b:%e\n\t\t|c:%d\n\t\t|d:%s\n\t\t|e:%s\n\t\t|f:%s\n\t\t|g:%e\n\n", a.a, a.b, a.c, a.d, a.e, a.f, a.g); return 0; }