1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
#include <iostream>
#include <boost/algorithm/string.hpp>
#include <snapper/AppUtil.h>
#include "GetOpts.h"
#include "text.h"
using namespace std;
using namespace snapper;
// based on getopt.cc from zypper, thanks jkupec
const struct option GetOpts::no_options[1] = {
{ 0, 0, 0, 0 }
};
void
GetOpts::init(int new_argc, char** new_argv)
{
argc = new_argc;
argv = new_argv;
}
GetOpts::parsed_opts
GetOpts::parse(const struct option* longopts)
{
return parse(NULL, longopts);
}
GetOpts::parsed_opts
GetOpts::parse(const char* command, const struct option* longopts)
{
parsed_opts result;
opterr = 0; // we report errors on our own
string optstring = make_optstring(longopts);
short2long_t short2long = make_short2long(longopts);
while (true)
{
int option_index = 0;
int c = getopt_long(argc, argv, optstring.c_str(), longopts, &option_index);
switch (c)
{
case -1:
return result;
case '?':
if (!command)
cerr << sformat(_("Unknown global option '%s'."), argv[optind - 1]) << endl;
else
cerr << sformat(_("Unknown option '%s' for command '%s'."), argv[optind - 1], command) << endl;
cerr << _("Try 'snapper --help' for more information.") << endl;
exit(EXIT_FAILURE);
case ':':
if (!command)
cerr << sformat(_("Missing argument for global option '%s'."), argv[optind - 1]) << endl;
else
cerr << sformat(_("Missing argument for command option '%s'."), argv[optind - 1]) << endl;
cerr << _("Try 'snapper --help' for more information.") << endl;
exit(EXIT_FAILURE);
default:
const char* opt = c ? short2long[c] : longopts[option_index].name;
result[opt] = optarg ? optarg : "";
break;
}
}
}
string
GetOpts::make_optstring(const struct option* longopts) const
{
// '+' - do not permute, stop at the 1st nonoption, which is the command or an argument
// ':' - return ':' to indicate missing arg, not '?'
string optstring = "+:";
for (; longopts && longopts->name; ++longopts)
{
if (!longopts->flag && longopts->val)
{
optstring += (char) longopts->val;
if (longopts->has_arg == required_argument)
optstring += ':';
else if (longopts->has_arg == optional_argument)
optstring += "::";
}
}
return optstring;
}
GetOpts::short2long_t
GetOpts::make_short2long(const struct option* longopts) const
{
short2long_t result;
for (; longopts && longopts->name; ++longopts)
{
if (!longopts->flag && longopts->val)
{
result[longopts->val] = longopts->name;
}
}
return result;
}
|