36 |
36 |
37 ArgParser::~ArgParser() |
37 ArgParser::~ArgParser() |
38 { |
38 { |
39 for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) |
39 for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) |
40 if(i->second.self_delete) |
40 if(i->second.self_delete) |
41 switch(i->second.type) { |
41 switch(i->second.type) { |
42 case BOOL: |
42 case BOOL: |
43 delete i->second.bool_p; |
43 delete i->second.bool_p; |
44 break; |
44 break; |
45 case STRING: |
45 case STRING: |
46 delete i->second.string_p; |
46 delete i->second.string_p; |
47 break; |
47 break; |
48 case DOUBLE: |
48 case DOUBLE: |
49 delete i->second.double_p; |
49 delete i->second.double_p; |
50 break; |
50 break; |
51 case INTEGER: |
51 case INTEGER: |
52 delete i->second.int_p; |
52 delete i->second.int_p; |
53 break; |
53 break; |
54 case UNKNOWN: |
54 case UNKNOWN: |
55 break; |
55 break; |
56 case FUNC: |
56 case FUNC: |
57 break; |
57 break; |
58 } |
58 } |
59 } |
59 } |
60 |
60 |
61 |
61 |
62 ArgParser &ArgParser::intOption(const std::string &name, |
62 ArgParser &ArgParser::intOption(const std::string &name, |
63 const std::string &help, |
63 const std::string &help, |
64 int value, bool obl) |
64 int value, bool obl) |
65 { |
65 { |
66 ParData p; |
66 ParData p; |
67 p.int_p=new int(value); |
67 p.int_p=new int(value); |
68 p.self_delete=true; |
68 p.self_delete=true; |
69 p.help=help; |
69 p.help=help; |
188 _opts[name]=p; |
188 _opts[name]=p; |
189 return *this; |
189 return *this; |
190 } |
190 } |
191 |
191 |
192 ArgParser &ArgParser::optionGroup(const std::string &group, |
192 ArgParser &ArgParser::optionGroup(const std::string &group, |
193 const std::string &opt) |
193 const std::string &opt) |
194 { |
194 { |
195 Opts::iterator i = _opts.find(opt); |
195 Opts::iterator i = _opts.find(opt); |
196 LEMON_ASSERT(i!=_opts.end(), "Unknown option: '"+opt+"'"); |
196 LEMON_ASSERT(i!=_opts.end(), "Unknown option: '"+opt+"'"); |
197 LEMON_ASSERT(!(i->second.ingroup), |
197 LEMON_ASSERT(!(i->second.ingroup), |
198 "Option already in option group: '"+opt+"'"); |
198 "Option already in option group: '"+opt+"'"); |
199 GroupData &g=_groups[group]; |
199 GroupData &g=_groups[group]; |
200 g.opts.push_back(opt); |
200 g.opts.push_back(opt); |
201 i->second.ingroup=true; |
201 i->second.ingroup=true; |
202 return *this; |
202 return *this; |
231 g.mandatory=true; |
231 g.mandatory=true; |
232 return *this; |
232 return *this; |
233 } |
233 } |
234 |
234 |
235 ArgParser &ArgParser::other(const std::string &name, |
235 ArgParser &ArgParser::other(const std::string &name, |
236 const std::string &help) |
236 const std::string &help) |
237 { |
237 { |
238 _others_help.push_back(OtherArg(name,help)); |
238 _others_help.push_back(OtherArg(name,help)); |
239 return *this; |
239 return *this; |
240 } |
240 } |
241 |
241 |
242 void ArgParser::show(std::ostream &os,Opts::iterator i) |
242 void ArgParser::show(std::ostream &os,Opts::iterator i) |
243 { |
243 { |
244 os << "-" << i->first; |
244 os << "-" << i->first; |
245 if(i->second.has_syn) |
245 if(i->second.has_syn) |
246 for(Opts::iterator j=_opts.begin();j!=_opts.end();++j) |
246 for(Opts::iterator j=_opts.begin();j!=_opts.end();++j) |
247 if(j->second.syn&&j->second.help==i->first) |
247 if(j->second.syn&&j->second.help==i->first) |
248 os << "|-" << j->first; |
248 os << "|-" << j->first; |
249 switch(i->second.type) { |
249 switch(i->second.type) { |
250 case STRING: |
250 case STRING: |
251 os << " str"; |
251 os << " str"; |
252 break; |
252 break; |
253 case INTEGER: |
253 case INTEGER: |
297 cstr << ' '; |
297 cstr << ' '; |
298 if(!g->second.mandatory) cstr << '['; |
298 if(!g->second.mandatory) cstr << '['; |
299 show(cstr,g); |
299 show(cstr,g); |
300 if(!g->second.mandatory) cstr << ']'; |
300 if(!g->second.mandatory) cstr << ']'; |
301 if(pos+cstr.str().size()>LINE_LEN) { |
301 if(pos+cstr.str().size()>LINE_LEN) { |
302 std::cerr << std::endl << indent; |
302 std::cerr << std::endl << indent; |
303 pos=indent.size(); |
303 pos=indent.size(); |
304 } |
304 } |
305 std::cerr << cstr.str(); |
305 std::cerr << cstr.str(); |
306 pos+=cstr.str().size(); |
306 pos+=cstr.str().size(); |
307 } |
307 } |
308 for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) |
308 for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) |
309 if(!i->second.ingroup&&!i->second.syn) { |
309 if(!i->second.ingroup&&!i->second.syn) { |
310 std::ostringstream cstr; |
310 std::ostringstream cstr; |
311 cstr << ' '; |
311 cstr << ' '; |
312 if(!i->second.mandatory) cstr << '['; |
312 if(!i->second.mandatory) cstr << '['; |
313 show(cstr,i); |
313 show(cstr,i); |
314 if(!i->second.mandatory) cstr << ']'; |
314 if(!i->second.mandatory) cstr << ']'; |
315 if(pos+cstr.str().size()>LINE_LEN) { |
315 if(pos+cstr.str().size()>LINE_LEN) { |
316 std::cerr << std::endl << indent; |
316 std::cerr << std::endl << indent; |
317 pos=indent.size(); |
317 pos=indent.size(); |
318 } |
318 } |
319 std::cerr << cstr.str(); |
319 std::cerr << cstr.str(); |
320 pos+=cstr.str().size(); |
320 pos+=cstr.str().size(); |
321 } |
321 } |
322 for(std::vector<OtherArg>::iterator i=_others_help.begin(); |
322 for(std::vector<OtherArg>::iterator i=_others_help.begin(); |
323 i!=_others_help.end();++i) |
323 i!=_others_help.end();++i) |
324 { |
324 { |
325 std::ostringstream cstr; |
325 std::ostringstream cstr; |
326 cstr << ' ' << i->name; |
326 cstr << ' ' << i->name; |
327 |
327 |
328 if(pos+cstr.str().size()>LINE_LEN) { |
328 if(pos+cstr.str().size()>LINE_LEN) { |
329 std::cerr << std::endl << indent; |
329 std::cerr << std::endl << indent; |
330 pos=indent.size(); |
330 pos=indent.size(); |
331 } |
331 } |
332 std::cerr << cstr.str(); |
332 std::cerr << cstr.str(); |
333 pos+=cstr.str().size(); |
333 pos+=cstr.str().size(); |
334 } |
334 } |
335 std::cerr << std::endl; |
335 std::cerr << std::endl; |
336 } |
336 } |
337 |
337 |
338 void ArgParser::showHelp() |
338 void ArgParser::showHelp() |
339 { |
339 { |
340 shortHelp(); |
340 shortHelp(); |
341 std::cerr << "Where:\n"; |
341 std::cerr << "Where:\n"; |
342 for(std::vector<OtherArg>::iterator i=_others_help.begin(); |
342 for(std::vector<OtherArg>::iterator i=_others_help.begin(); |
343 i!=_others_help.end();++i) showHelp(i); |
343 i!=_others_help.end();++i) showHelp(i); |
344 for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i); |
344 for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i); |
345 exit(1); |
345 exit(1); |
346 } |
346 } |
347 |
347 |
348 |
348 |
349 void ArgParser::unknownOpt(std::string arg) |
349 void ArgParser::unknownOpt(std::string arg) |
350 { |
350 { |
351 std::cerr << "\nUnknown option: " << arg << "\n"; |
351 std::cerr << "\nUnknown option: " << arg << "\n"; |
352 std::cerr << "\nType '" << _command_name << |
352 std::cerr << "\nType '" << _command_name << |
353 " --help' to obtain a short summary on the usage.\n\n"; |
353 " --help' to obtain a short summary on the usage.\n\n"; |
354 exit(1); |
354 exit(1); |
355 } |
355 } |
356 |
356 |
357 void ArgParser::requiresValue(std::string arg, OptType t) |
357 void ArgParser::requiresValue(std::string arg, OptType t) |
358 { |
358 { |
359 std::cerr << "Argument '" << arg << "' requires a"; |
359 std::cerr << "Argument '" << arg << "' requires a"; |
360 switch(t) { |
360 switch(t) { |
361 case STRING: |
361 case STRING: |
362 std::cerr << " string"; |
362 std::cerr << " string"; |
371 break; |
371 break; |
372 } |
372 } |
373 std::cerr << " value\n\n"; |
373 std::cerr << " value\n\n"; |
374 showHelp(); |
374 showHelp(); |
375 } |
375 } |
376 |
376 |
377 |
377 |
378 void ArgParser::checkMandatories() |
378 void ArgParser::checkMandatories() |
379 { |
379 { |
380 bool ok=true; |
380 bool ok=true; |
381 for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) |
381 for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) |
382 if(i->second.mandatory&&!i->second.set) |
382 if(i->second.mandatory&&!i->second.set) |
383 { |
383 { |
384 if(ok) |
384 if(ok) |
385 std::cerr << _command_name |
385 std::cerr << _command_name |
386 << ": The following mandatory arguments are missing.\n"; |
386 << ": The following mandatory arguments are missing.\n"; |
387 ok=false; |
387 ok=false; |
388 showHelp(i); |
388 showHelp(i); |
389 } |
389 } |
390 for(Groups::iterator i=_groups.begin();i!=_groups.end();++i) |
390 for(Groups::iterator i=_groups.begin();i!=_groups.end();++i) |
391 if(i->second.mandatory||i->second.only_one) |
391 if(i->second.mandatory||i->second.only_one) |
392 { |
392 { |
393 int set=0; |
393 int set=0; |
394 for(GroupData::Opts::iterator o=i->second.opts.begin(); |
394 for(GroupData::Opts::iterator o=i->second.opts.begin(); |
395 o!=i->second.opts.end();++o) |
395 o!=i->second.opts.end();++o) |
396 if(_opts.find(*o)->second.set) ++set; |
396 if(_opts.find(*o)->second.set) ++set; |
397 if(i->second.mandatory&&!set) { |
397 if(i->second.mandatory&&!set) { |
398 std::cerr << _command_name |
398 std::cerr << _command_name |
399 << ": At least one of the following arguments is mandatory.\n"; |
399 << ": At least one of the following arguments is mandatory.\n"; |
400 ok=false; |
400 ok=false; |
401 for(GroupData::Opts::iterator o=i->second.opts.begin(); |
401 for(GroupData::Opts::iterator o=i->second.opts.begin(); |
402 o!=i->second.opts.end();++o) |
402 o!=i->second.opts.end();++o) |
403 showHelp(_opts.find(*o)); |
403 showHelp(_opts.find(*o)); |
404 } |
404 } |
405 if(i->second.only_one&&set>1) { |
405 if(i->second.only_one&&set>1) { |
406 std::cerr << _command_name |
406 std::cerr << _command_name |
407 << ": At most one of the following arguments can be given.\n"; |
407 << ": At most one of the following arguments can be given.\n"; |
408 ok=false; |
408 ok=false; |
409 for(GroupData::Opts::iterator o=i->second.opts.begin(); |
409 for(GroupData::Opts::iterator o=i->second.opts.begin(); |
410 o!=i->second.opts.end();++o) |
410 o!=i->second.opts.end();++o) |
411 showHelp(_opts.find(*o)); |
411 showHelp(_opts.find(*o)); |
412 } |
412 } |
413 } |
413 } |
414 if(!ok) { |
414 if(!ok) { |
415 std::cerr << "\nType '" << _command_name << |
415 std::cerr << "\nType '" << _command_name << |
416 " --help' to obtain a short summary on the usage.\n\n"; |
416 " --help' to obtain a short summary on the usage.\n\n"; |
417 exit(1); |
417 exit(1); |
418 } |
418 } |
419 } |
419 } |
420 |
420 |
421 ArgParser &ArgParser::parse() |
421 ArgParser &ArgParser::parse() |
422 { |
422 { |
423 for(int ar=1; ar<_argc; ++ar) { |
423 for(int ar=1; ar<_argc; ++ar) { |
424 std::string arg(_argv[ar]); |
424 std::string arg(_argv[ar]); |
425 if (arg[0] != '-' || arg.size() == 1) { |
425 if (arg[0] != '-' || arg.size() == 1) { |
426 _file_args.push_back(arg); |
426 _file_args.push_back(arg); |
427 } |
427 } |
428 else { |
428 else { |
429 Opts::iterator i = _opts.find(arg.substr(1)); |
429 Opts::iterator i = _opts.find(arg.substr(1)); |
430 if(i==_opts.end()) unknownOpt(arg); |
430 if(i==_opts.end()) unknownOpt(arg); |
431 else { |
431 else { |
432 if(i->second.syn) i=_opts.find(i->second.help); |
432 if(i->second.syn) i=_opts.find(i->second.help); |
433 ParData &p(i->second); |
433 ParData &p(i->second); |
434 if (p.type==BOOL) *p.bool_p=true; |
434 if (p.type==BOOL) *p.bool_p=true; |
435 else if (p.type==FUNC) p.func_p.p(p.func_p.data); |
435 else if (p.type==FUNC) p.func_p.p(p.func_p.data); |
436 else if(++ar==_argc) requiresValue(arg, p.type); |
436 else if(++ar==_argc) requiresValue(arg, p.type); |
437 else { |
437 else { |
438 std::string val(_argv[ar]); |
438 std::string val(_argv[ar]); |
439 std::istringstream vals(val); |
439 std::istringstream vals(val); |
440 switch(p.type) { |
440 switch(p.type) { |
441 case STRING: |
441 case STRING: |
442 *p.string_p=val; |
442 *p.string_p=val; |
443 break; |
443 break; |
444 case INTEGER: |
444 case INTEGER: |
445 vals >> *p.int_p; |
445 vals >> *p.int_p; |
446 break; |
446 break; |
447 case DOUBLE: |
447 case DOUBLE: |
448 vals >> *p.double_p; |
448 vals >> *p.double_p; |
449 break; |
449 break; |
450 default: |
450 default: |
451 break; |
451 break; |
452 } |
452 } |
453 if(p.type!=STRING&&(!vals||!vals.eof())) |
453 if(p.type!=STRING&&(!vals||!vals.eof())) |
454 requiresValue(arg, p.type); |
454 requiresValue(arg, p.type); |
455 } |
455 } |
456 p.set = true; |
456 p.set = true; |
457 } |
457 } |
458 } |
458 } |
459 } |
459 } |
460 checkMandatories(); |
460 checkMandatories(); |
461 |
461 |
462 return *this; |
462 return *this; |
463 } |
463 } |
464 |
464 |
465 } |
465 } |