summaryrefslogtreecommitdiff
path: root/option.cc
diff options
context:
space:
mode:
Diffstat (limited to 'option.cc')
-rw-r--r--option.cc132
1 files changed, 132 insertions, 0 deletions
diff --git a/option.cc b/option.cc
new file mode 100644
index 00000000..586037b1
--- /dev/null
+++ b/option.cc
@@ -0,0 +1,132 @@
+#include "option.h"
+
+#include <iostream>
+#include <cstdarg>
+
+option_handler::option_handler(const std::string& label,
+ const std::string& opt_chars,
+ const bool _multiple)
+ : handled(false), multiple(_multiple)
+{
+ option_t opt;
+
+ for (const char * q = label.c_str(); *q; q++)
+ if (*q == '_')
+ opt.long_opt += '-';
+ else
+ opt.long_opt += *q;
+
+ handlers.insert(option_handler_pair(opt.long_opt, this));
+
+ if (! opt_chars.empty()) {
+ if (opt_chars[0] != ':')
+ opt.short_opt = opt_chars[0];
+
+ if (opt_chars[opt_chars.length() - 1] == ':')
+ opt.wants_arg = true;
+ }
+
+ opt.handler = this;
+
+ options.push_back(opt);
+}
+
+bool process_option(const std::string& opt, const char * arg)
+{
+ option_handler_map::iterator handler = option_handler::handlers.find(opt);
+ if (handler != option_handler::handlers.end() &&
+ (! (*handler).second->handled || (*handler).second->multiple)) {
+ (*handler).second->handle_option(arg);
+ (*handler).second->handled = true;
+ return true;
+ }
+ return false;
+}
+
+static inline void process_option(const option_t& opt,
+ const char * arg = NULL) {
+ if (! opt.handler->handled || opt.handler->multiple) {
+ opt.handler->handle_option(arg);
+ opt.handler->handled = true;
+ }
+}
+
+void process_arguments(std::vector<char *>& args, int argc, char ** argv)
+{
+ int index = 1;
+ for (char ** i = argv + 1; index < argc; i++, index++) {
+ if ((*i)[0] != '-') {
+ args.push_back(*i);
+ continue;
+ }
+
+ // --long-option
+ again:
+ if ((*i)[1] == '-') {
+ for (std::vector<option_t>::iterator j
+ = option_handler::options.begin();
+ j != option_handler::options.end();
+ j++)
+ if ((*j).wants_arg) {
+ if (const char * p = std::strchr(*i + 2, '=')) {
+ if ((*j).long_opt == std::string(*i + 2, p - (*i + 2))) {
+ process_option(*j, p + 1);
+ goto next;
+ }
+ }
+ else if ((*j).long_opt == *i + 2) {
+ process_option(*j, argv[++index]);
+ goto next;
+ }
+ }
+ else if ((*j).long_opt == *i + 2) {
+ process_option(*j);
+ goto next;
+ }
+
+ std::cerr << "Error: illegal option " << *i << std::endl;
+ std::exit(1);
+ } else {
+ for (std::vector<option_t>::iterator j
+ = option_handler::options.begin();
+ j != option_handler::options.end();
+ j++)
+ if ((*i)[1] == (*j).short_opt) {
+ if ((*j).wants_arg) {
+ process_option(*j, argv[++index]);
+ goto next;
+ } else {
+ process_option(*j);
+ if ((*i)[2]) {
+ std::strcpy(*i + 1, *i + 2);
+ goto again;
+ }
+ goto next;
+ }
+ }
+
+ std::cerr << "Error: illegal option -- " << (*i)[1] << std::endl;
+ std::exit(1);
+ }
+
+ next:
+ ;
+ }
+}
+
+void process_environment(char ** envp)
+{
+ for (char ** p = envp; *p; p++)
+ if (std::strncmp(*p, "LEDGER_", 7) == 0) {
+ std::string opt;
+ char * q;
+ for (q = *p + 7; *q && *q != '='; q++)
+ if (*q == '_')
+ opt += '-';
+ else
+ opt += std::tolower(*q);
+
+ if (*q == '=')
+ process_option(opt, q + 1);
+ }
+}