80 int CommandLine::ProcessCommandLine(
int argc,
char** argv,
string PrgmDesc,
81 string& Usage,
string& Errors, vector<string>& Unrecog)
88 if(ConfigureLOG::ReportingLevel() >= ConfigureLOG::Level(
"DEBUG")) {
89 debug = ConfigureLOG::ReportingLevel()-4;
90 LOG(
DEBUG) <<
"CommandLine sets debug to "
91 << ConfigureLOG::ToString(ConfigureLOG::ReportingLevel());
95 helponly = foundErrors =
false;
100 if(syntaxPageBuilt == 0) {
101 word = string(argv[0]);
102 string::size_type
pos =
word.find_last_of(
"/\\");
104 syntaxPage =
"Usage: " +
word +
" [option] ...";
107 if(syntaxPageBuilt == 1) {
108 syntaxPage +=
"\n" + PrgmDesc +
"\n";
113 if(!ValidateCommandLine(
word)) {
122 Usage = SyntaxPage();
126 if(argc==1 && requireOneArg) helponly =
true;
130 for(j=1; j<argc; j++) PreProcessArgs(argv[j],Args,Errors);
131 LOG(
DEBUG) <<
"Return from CommandLine::PreProcessArgs: help is "
132 << (
help ?
"T":
"F") <<
" and helponly is " << (helponly ?
"T":
"F");
135 if((requireOneArg && Args.size() == 0) || helponly)
help =
true;
139 oss <<
"CommandLine argument list passed to parser:" << endl;
140 for(
size_t k=0; k<Args.size(); k++)
141 oss <<
" arg[" << k <<
"] = " << Args[k] << endl;
150 Parse(Args, Errors, Unrecog);
153 Postprocess(Errors, Unrecog);
159 if(!Errors.empty()) {
169 catch(std::exception& e) {
180 void CommandLine::DumpConfiguration(ostream& os,
string tag)
187 vector<string> values;
188 string::size_type
pos;
192 for(i=0; i<options.size(); i++) {
193 if(!tag.empty()) os << tag <<
" ";
194 if(options[i].predesc.size()) {
195 str = options[i].predesc;
196 if(str[0] ==
'#' || str[0] ==
'\n') ;
197 else str = string(
" ") + str;
199 if(!tag.empty()) os << tag <<
" ";
202 str = options[i].desc;
203 os <<
" " << str <<
" (--" << options[i].longOpt <<
") : ";
206 switch(options[i].type) {
208 os << (*((
bool *)(options[i].p_output)) ?
"true" :
"false");
211 os << *((
int *)(options[i].p_output));
213 case typeVectorInt: {
214 vector<int> ints(*((vector<int> *)(options[i].p_output)));
217 else for(j=0; j<ints.size(); j++)
218 os << ints[j] << (j==ints.size()-1 ?
"" :
",");
222 d = *((
double *)(options[i].p_output));
223 if(d == 0 || fabs(d) >= 0.1)
224 os << fixed << setprecision(2) << d;
225 else if(fabs(d) >= 0.01)
226 os << fixed << setprecision(3) << d;
228 os << scientific << setprecision(2) << d;
231 if((*((
string *)(options[i].p_output))).empty())
234 str = *((
string *)(options[i].p_output));
236 case typeVectorString:
237 values = *((vector<string> *)(options[i].p_output));
238 if(values.size() == 0)
240 else for(j=0; j<values.size(); j++)
241 str += values[j] + (j==values.size()-1 ?
"" :
",");
250 case typeVectorSat: {
251 vector<RinexSatID> sats(*((vector<RinexSatID> *)(options[i].p_output)));
252 if(sats.size() == 0) os <<
"<none>";
254 for(j=0; j<sats.size(); j++)
255 str += sats[j].toString() + (j==sats.size()-1 ?
"" :
",");
264 pos = str.find_first_of(
" \t");
265 if(
pos != string::npos) str = string(
"\"") + str + string(
"\"");
274 os <<
" Print extended output, including cmdline summary (--verbose) : "
275 << (verbose?
"true":
"false") << endl;
276 os <<
" Print debug output at level DEBUGn [n=0-7] (--debug<n>) : "
278 os <<
" Print this syntax page and quit (--help) : "
279 << (
help?
"true":
"false") << endl;
283 catch(std::exception& e) {
294 bool CommandLine::ValidateCommandLine(
string& msg)
299 string tag(
"Error (CommandLine): option ");
302 LOG(
DEBUG) <<
"CommandLine::ValidateCommandLine()";
304 for(i=0; i<options.size(); i++) {
305 string opt(
"--" + options[i].longOpt);
309 oss << tag << options[i].longOpt
310 <<
" (with arg) is both valid and to be ignored.\n";
313 if(
vectorindex(ignore_opts_without_arg,opt) != -1) {
315 oss << tag << options[i].longOpt
316 <<
" (w/o arg) is both valid and to be ignored.\n";
321 oss << tag << options[i].longOpt
322 <<
" is both valid and an 'ignore on' option.\n";
327 oss << tag << options[i].longOpt
328 <<
" is both valid and an 'ignore off' option.\n";
333 if(options[i].longOpt == options[j].longOpt) {
335 oss << tag <<
"'" << options[i].longOpt <<
"' is repeated.\n";
337 if(options[i].shortOpt != 0 && options[i].shortOpt == options[j].shortOpt) {
339 oss << tag <<
"'" << options[i].longOpt
340 <<
"' short form is already used in option '" << options[j].longOpt
347 map<string,string>::const_iterator it;
348 for(it=deprec_opts.begin(); it != deprec_opts.end(); ++it) {
349 LOG(
DEBUG) <<
"Test deprec option " << it->first <<
" -> " << it->second;
351 for(i=0; i<options.size(); i++) {
352 if(it->second ==
string(
"--") + options[i].longOpt ||
353 it->second ==
string(
"-") + options[i].shortOpt)
354 { found=
true;
break; }
358 oss << tag << it->second <<
", the replacement for deprecated option "
359 << it->first <<
", is not found.\n";
365 if(!msg.empty()) {
LOG(
DEBUG) <<
"ValidateCommandLine finds " << msg; }
371 catch(std::exception& e) {
381 void CommandLine::BuildSyntaxPage(
void)
390 for(i=0; i<options.size(); i++) {
391 j = options[i].longOpt.length() + options[i].arg.length() + 7;
392 if(j > optionsize) optionsize = j;
396 for(i=0; i<options.size(); i++) {
398 if(options[i].type < typeBool || options[i].type >= typeCount)
402 option =
" --" + options[i].longOpt;
403 if(options[i].
arg.length())
option +=
" <" + options[i].arg +
"> ";
407 switch(options[i].type) {
409 deflt = ( *(
bool *)(options[i].p_output) ?
"do" :
"don't");
412 deflt =
asString(*(
int *)(options[i].p_output));
414 case typeVectorInt: {
415 vector<int> *iptr = (vector<int> *)(options[i].p_output);
417 for(j=0; j<iptr->size(); j++)
418 deflt += (j>0 ?
",":
"") +
asString((*iptr)[j]);
422 d = *((
double *)(options[i].p_output));
423 if(d == 0 || fabs(d) >= 0.1)
425 else if(fabs(d) >= 0.01)
433 deflt = *(
string *)(options[i].p_output);
435 case typeVectorString: {
436 vector<string> *sptr = (vector<string> *)(options[i].p_output);
438 for(j=0; j<sptr->size(); j++)
439 deflt += (j>0 ?
",":
"") + (*sptr)[j];
444 if(gptr->
id != -1) deflt = (*gptr).
toString();
445 else deflt = string(
"");
448 case typeVectorSat: {
449 vector<RinexSatID> *gptr = (vector<RinexSatID> *)(options[i].p_output);
451 for(k=0,j=0; j<gptr->size(); j++)
452 if((*gptr)[j].
id > 0)
453 deflt += (k++>0 ?
",":
"") + (*gptr)[j].toString();
462 options[i].syntax = options[i].predesc
463 + (options[i].predesc.size() ?
"\n" :
"")
466 + (options[i].repeat ?
" [repeatable]" :
"")
467 +
" (" + deflt +
")";
472 catch(std::exception& e) {
483 void CommandLine::PreProcessArgs(
const char *in_arg, vector<string>& Args,
487 static bool found_cfg_file=
false;
488 static bool ignore_opts=
false;
489 static bool ignore_once=
false;
491 string msg,sarg(in_arg);
493 if(sarg ==
string())
return;
494 LOG(
DEBUG) <<
"CommandLine::PreProcess arg " << sarg;
496 if(ignore_once) { ignore_once =
false;
return; }
499 for(i=0; i<ignore_opts_without_arg.size(); i++) {
500 if(sarg == ignore_opts_without_arg[i]) {
501 LOG(
DEBUG) <<
"CommandLine::PreProcess: ignoring option " << sarg;
506 for(i=0; i<ignore_opts_with_arg.size(); i++) {
507 if(sarg == ignore_opts_with_arg[i]) {
508 LOG(
DEBUG) <<
"CommandLine::PreProcess: ignoring option " << sarg
509 <<
" and its argument";
515 for(i=0; i<ignore_on_opts.size(); i++) {
516 if(sarg == ignore_on_opts[i]) {
517 LOG(
DEBUG) <<
"CommandLine::PreProcess: start ignoring options: " << sarg;
523 for(i=0; i<ignore_off_opts.size(); i++) {
524 if(sarg == ignore_off_opts[i]) {
525 LOG(
DEBUG) <<
"CommandLine::PreProcess: stop ignoring options: " << sarg;
532 LOG(
DEBUG) <<
"CommandLine::PreProcess: ignoring option " << sarg;
537 if(sarg ==
"--file" || sarg ==
"-f")
538 found_cfg_file =
true;
541 else if(found_cfg_file || (in_arg[0]==
'-' && in_arg[1]==
'f')) {
542 string filename(in_arg);
543 if(!found_cfg_file) filename.erase(0,2);
else found_cfg_file =
false;
544 LOG(
DEBUG) <<
"CommandLine::PreProcess found a file of options: " << filename;
545 ifstream infile(filename.c_str());
547 LOG(
ERROR) <<
"Error: could not open options file " << filename;
551 bool again_cfg_file=
false;
554 getline(infile,buffer);
560 while(!buffer.empty()) {
564 again_cfg_file =
false;
565 PreProcessArgs(
word.c_str(),Args,Errors);
567 else if(
word[0] ==
'#') {
570 else if(
word ==
"--file" ||
word ==
"-f")
571 again_cfg_file =
true;
572 else if(
word[0] ==
'"') {
574 buffer =
"dummy " + buffer;
575 PreProcessArgs(
word.c_str(),Args,Errors);
578 PreProcessArgs(
word.c_str(),Args,Errors);
582 if(infile.eof() || !infile.good())
break;
589 else if(sarg==
string(
"-h") || sarg==
string(
"--help")) {
591 LOG(
DEBUG) <<
"CommandLine::PreProcess found help option";
593 else if(sarg.substr(0,2)==
string(
"-d") || sarg.substr(0,7)==
string(
"--debug")) {
594 string level(
"DEBUG");
595 if(sarg==
string(
"-d") || sarg==
string(
"--debug"))
598 debug =
asInt(sarg[1]==
'd' ? sarg.substr(2) : sarg.substr(7));
602 ConfigureLOG::ReportingLevel() = ConfigureLOG::Level(level.c_str());
603 LOG(
DEBUG) <<
"CommandLine found debug option at level " <<
debug
604 <<
", logging level "
605 << ConfigureLOG::ToString(ConfigureLOG::ReportingLevel());
609 else if(sarg==
string(
"-v") || sarg==
string(
"--verbose")) {
613 ConfigureLOG::ReportingLevel() = ConfigureLOG::Level(
"VERBOSE");
614 LOG(
DEBUG) <<
"CommandLine::PreProcess found the verbose option";
619 else if(deprec_opts.find(sarg) != deprec_opts.end())
620 Args.push_back(deprec_opts[sarg]);
624 LOG(
DEBUG) <<
"CommandLine::PreProcess found regular arg " << sarg;
625 Args.push_back(sarg);
629 catch(std::exception& e) {
639 void expand_args(vector<string>& oldvalues, vector<string>& newvalues,
string& msg)
644 for(
size_t k=0; k<oldvalues.size(); k++) {
646 if(
arg.substr(0,1) ==
"@") {
648 string filename(
arg.substr(1));
655 msg +=
" Error - Argument list file " + filename
656 +
" could not be opened.";
659 else LOG(
DEBUG) <<
"Opened arg list file " << filename;
662 newvalues.push_back(
arg);
668 catch(std::exception& e) {
679 void CommandLine::Parse(vector<string>& Args,
string& Errors, vector<string>& Unrecog)
687 while(i < Args.size()) {
690 for(j=0; j<options.size(); ++j) {
691 if((
arg.size() == 2 &&
arg[0] ==
'-' &&
arg[1] == options[j].shortOpt) ||
692 (
arg.substr(0,2) ==
"--" &&
arg.substr(2) == options[j].longOpt))
694 if(options[j].type > typeBool) {
695 if(i == Args.size()-1) {
696 Errors +=
"Error - option " +
arg +
" without value.\n";
699 else if(Args[i+1].substr(0,2) ==
"--") {
700 Errors +=
"Error - option " +
arg +
" without value.\n";
703 else val = Args[++i];
705 else val = string(
"T");
707 LOG(
DEBUG) <<
"CommandLine::Parse found arg[" << i <<
"] "
708 <<
arg <<
" = " << val;
709 options[j].values.push_back(val);
715 if(j == options.size()) {
716 Unrecog.push_back(Args[i]);
717 LOG(
DEBUG) <<
"CommandLine::Parse found unrecognized arg[" << i <<
"] "
728 for(j=0; j<options.size(); ++j) {
732 if(
help && options[j].longOpt ==
string(
"help")) {
733 LOG(
DEBUG) <<
"CommandLine::Parse found help option and help";
734 *((
bool *)(options[j].p_output)) =
help;
735 options[j].values.push_back(
string(
"T"));
737 else if(verbose && options[j].longOpt ==
string(
"verbose")) {
738 LOG(
DEBUG) <<
"CommandLine::Parse found verbose option and verbose";
739 *((
bool *)(options[j].p_output)) = verbose;
740 options[j].values.push_back(
string(
"T"));
742 else if(
debug > -1 && options[j].longOpt ==
string(
"debug")) {
743 LOG(
DEBUG) <<
"CommandLine::Parse found debug option and debug = " <<
debug;
744 *((
int *)(options[j].p_output)) =
debug;
749 if(options[j].required && options[j].values.size() == 0)
750 Errors +=
"Required option " + options[j].longOpt +
" is not found.\n";
753 if(!options[j].repeat && options[j].values.size() > 1)
754 Errors +=
"Not-repeatable option "+options[j].longOpt+
" was repeated.\n";
759 catch(std::exception& e) {
769 string CommandLine::SyntaxPage(
void)
772 if(syntaxPageBuilt == 2) {
773 if(options.size() > 0)
774 for(
int i=0; i<options.size(); i++)
776 syntaxPage += options[i].syntax +
"\n";
781 +
"Print extended output, including cmdline summary (don't)\n";
782 syntaxPage +=
leftJustify(
" --debug<n>",optionsize)
783 +
"Print debug output at LOGlevel n [n=0-7] (-1)\n";
785 +
"Print this syntax page and quit (don't)";
793 catch(std::exception& e) {
803 void CommandLine::Postprocess(
string& Errors, vector<string>& Unrecog)
809 vector<string> values;
813 for(i=0; i<options.size(); i++) {
816 if(options[i].values.size() == 0)
continue;
817 LOG(
DEBUG) <<
"CommandLine::Postprocess parse " << options[i].longOpt
818 <<
" of type " << options[i].type << (options[i].doc ?
"":
" undocumented");
821 if(options[i].type == typeBool) {
822 *((
bool *)(options[i].p_output)) = ( options[i].toggle ?
823 ! (*((
bool *)(options[i].p_output))) :
true );
828 values = options[i].values;
831 if(options[i].expand && (options[i].type == typeVectorString ||
832 options[i].type == typeVectorSat ||
833 options[i].type == typeVectorInt))
835 vector<string> nvalues;
838 oss << errStr <<
" for option --" << options[i].longOpt <<
"\n";
842 switch(options[i].type) {
848 oss <<
"Error: non-integer value for --" << options[i].longOpt
849 <<
": " << values[0] << endl;
851 *((
int *)(options[i].p_output)) =
asInt(values[0]);
855 for(k=0; k<values.size(); k++) {
857 oss <<
"Error: non-integer value for --" << options[i].longOpt
858 <<
": " << values[k] << endl;
860 ((vector<int> *)(options[i].p_output))->push_back(
asInt(values[k]));
866 oss <<
"Error: invalid value for --" << options[i].longOpt
867 <<
": " << values[0] << endl;
869 *((
double *)(options[i].p_output))=
asDouble(values[0]);
873 *((
string *)(options[i].p_output)) = values[0];
876 case typeVectorString:
877 for(k=0; k<values.size(); k++)
878 ((vector<string> *)(options[i].p_output))->push_back(values[k]);
887 for(k=0; k<values.size(); k++) {
889 ((vector<RinexSatID> *)(options[i].p_output))->push_back(sat);
910 catch(std::exception& e) {