// Copyright (C) 2001 Claus Dręby // Terms of use are in the file COPYING #include #include #include "optmap.h" using namespace std; using namespace options_utils; optmap::optmap(const char* usage) : i(1), prog("program"), tail(usage) { } optmap::~optmap() { for (group_t::iterator p = group.begin(); p != group.end(); ++p) delete p->first; } optmap& optmap::add(const char* c, cmd* h) { if (cmds.find(c) != cmds.end()) throw invalid_argument(string("duplicated option: ")+c); cmds[c] = h; if (group[h].size() == 0) gvec.push_back(h); group[h].push_back(c); return *this; } optmap& optmap::alias(const char* new_opt, const char* old_opt) { cmd* h = cmds[old_opt]; if (!h) throw invalid_argument(string("no alias: ")+old_opt); return add(new_opt, h); } bool optmap::parse(int c, const char** v) { argc = c; argv = v; prog = argv[0]; for (; i < argc; ++i) { multichar = false; const char* s = argv[i]; size_t l = strlen(s); if (*s != '-' || l == 1) return true; if (s[1] == '-') { if (l == 2) { // end of options marker `--' ++i; return true; } if (!do_cmd(s+2)) return false; } else { char cmd[2]; cmd[1] = '\0'; multichar = l > 2; first_multi = true; for (const char* p = s+1; *p; ++p) { cmd[0] = *p; if (!do_cmd(cmd)) return false;; first_multi = false; if (!multichar) // get_arg used it break; } } } return true; } const char* optmap::get_arg() { if (multichar) { if (!first_multi) { cerr << "internal option requires argument " << argv[i] << endl; return 0; } multichar = false; return argv[i]+2; } return i < argc - 1 ? argv[++i] : 0; } void optmap::usage(bool abort) { cerr << "usage: " << prog; for (gvec_t::iterator p = gvec.begin(); p != gvec.end(); ++p) { cmd* h = *p; vector& v(group[h]); string arg = h->arg(); bool need_par = arg.size() > 0 && v.size() > 1; bool first = true; cerr << " ["; if (need_par) cerr << "("; for (vector::iterator s = v.begin(); s != v.end(); ++s) { cerr << (first ? " " : " | ") << (s->size() != 1 ? "--":"-") << *s; first = false; } if (need_par) cerr << ")"; if (arg.size()) cerr << ' ' << arg; cerr << " ]"; } cerr << (tail.size() ? " " : "") << tail << endl; if (abort) exit(1); } bool optmap::do_cmd(const string& opt) { cmd* c = cmds[opt]; if (!c) { cerr << "unknown option: " << opt << endl; return false; } return c->do_cmd(this); } bool opt_int::do_cmd(optmap* om) { const char* arg = om->get_arg(); if (!arg) return false; char* end; int v = strtol(arg, &end, 10); if (*end) { cerr << "failed to parse int argument: " << arg << endl; return false; } val = v; return true; } bool opt_string::do_cmd(optmap* om) { const char* arg = om->get_arg(); if (!arg) return false; val = arg; return true; }