//==========================================================================
// ARGS.CC - part of
// OMNeT++/OMNEST
// Discrete System Simulation in C++
//
// Command line argument handling
//
// Author: Andras Varga
//
//==========================================================================
#include <cstring>
#include <cstdio>
#include "common/opp_ctype.h"
#include "args.h"
using namespace omnetpp::common;
namespace omnetpp {
namespace envir {
ArgList::ArgList()
{
argc = 0;
argv = nullptr;
}
// args.parse(argc, argv, "h?f:u:l:c:r:n:p:x:X:q:agGvwsm");
/*
--debug-on-errors=true
--record-eventlog=true
--sim-time-limit=1000s
--**.serviceTime=100ms
*/
void ArgList::parse(int argc, char *argv[], const char *spec)
{
this->argc = argc;
this->argv = argv;
this->spec = spec;
int i;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "--") == 0) {
// 选项停止,直接退出
i++;
break;
}
// 处理长参数
if (argv[i][0] == '-' && argv[i][1] == '-') {
// long option -- treat it liberally for now
const char *eqpos = strchr(argv[i], '=');
if (eqpos)
longOpts[std::string(argv[i]+2, eqpos-argv[i]-2)] = eqpos+1;
// 如果是没有=,则认为是参数名;
// 最后一个argv,没有设置参数值,则设置为空; 如果不是最后一个,则值设置为下一个argv
else if (i == argc-1)
longOpts[argv[i]+2] = "";
else {
longOpts[argv[i]+2] = argv[i+1];
i++;
}
}
// 处理短参数
else if (argv[i][0] == '-') {
// short option
char c = argv[i][1];
if (!isValidOption(c))
throw opp_runtime_error("Invalid command-line option %s, try -h for help", argv[i]);
// 短参数字符对应的数组,
std::vector<std::string>& v = shortOpts[c]; // get or create map element
if (hasArg(c)) {
// 把2个字符后面的作为值存储 -cHello
if (argv[i][2])
v.push_back(argv[i]+2);
// 如果中间有空格,不是最后一个argv,则把下一个argv作为值 -c hello
else if (i < argc-1)
v.push_back(argv[++i]);
// 否则,没有值,就不对了
else if (!hasOptionalArg(c))
throw opp_runtime_error("command-line option %s is missing required argument", argv[i]);
}
else {
if (argv[i][2])
throw opp_runtime_error("command-line option -%c expects no argument", argv[i][1]);
}
}
else {
// non-option arg before '--',其他情况,不是--c=1, -c hello这样的
params.push_back(argv[i]);
}
}
// '--'后面的argv 都写到这个数组里
for ( ; i < argc; i++) {
params.push_back(argv[i]);
}
}
bool ArgList::isValidOption(char c) const
{
return strchr(spec.c_str(), c) != nullptr;
}
bool ArgList::hasArg(char c) const
{
const char *p = strchr(spec.c_str(), c);
return p && (*(p+1) == ':' || *(p+1) == '?');
}
bool ArgList::hasOptionalArg(char c) const
{
const char *p = strchr(spec.c_str(), c);
return p && *(p+1) == '?';
}
std::map<std::string, std::string> ArgList::getLongOptions() const
{
return longOpts;
}
bool ArgList::optionGiven(char c) const
{
return shortOpts.find(c) != shortOpts.end();
}
const char *ArgList::optionValue(char c, int k) const
{
if (shortOpts.find(c) == shortOpts.end())
return nullptr;
const std::vector<std::string>& v = shortOpts.find(c)->second;
return (k >= 0 && k < (int)v.size()) ? v[k].c_str() : nullptr;
}
const char *ArgList::argument(int k) const
{
return (k >= 0 && k < (int)params.size()) ? params[k].c_str() : nullptr;
}
} // namespace envir
} // namespace omnetpp