]> cygwin.com Git - cygwin-apps/setup.git/blobdiff - libgetopt++/src/OptionSet.cc
Merged across diffs between setup_crypto_branch_branchpoint and
[cygwin-apps/setup.git] / libgetopt++ / src / OptionSet.cc
index 66f88e3a24da2844bf545d1c5f412d1fc74823cc..bc3f018b32d34cc529308252ca420e2a6f7c63a4 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2002 Robert Collins.
+ * Copyright (c) 2003 Robert Collins.
  *
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License as published by
 #endif
 #include "getopt++/OptionSet.h"
 #include "getopt++/Option.h"
+#include "getopt++/DefaultFormatter.h"
 
 #include <iostream>
+#include <algorithm>
 
-OptionSet::OptionSet () : options(0), optCount (0) {}
-OptionSet::~OptionSet ()
+using namespace std;
+
+bool
+OptionSet::isOption(string::size_type pos) const
 {
-  delete[] options;
+    return pos == 1 || pos == 2;
 }
 
 void
-OptionSet::Init()
+OptionSet::processOne()
 {
-  options = 0;
-  optCount = 0;
+    string &option (argv[0]);
+    string::size_type pos = option.find_first_not_of("-");
+
+    if (!isOption(pos)) {
+        /* Push the non option into storage */
+       if (nonOptionHandler) {
+           lastResult = nonOptionHandler->Process(option.c_str());
+       } else {
+           nonoptions.push_back(option);
+           lastResult = Option::Ok;
+       }
+    } else {
+       doOption(option, pos);
+    }
 }
 
-bool OptionSet::Process (int argc, char **argv, OptionSet *defaultOptionSet)
+Option *
+OptionSet::findOption(string &option, string::size_type const &pos) const
 {
-  if (argc == 1)
-    {
-//      log (LOG_TIMESTAMP, "No command line options pass\n");
-      return true;
+    Option *theOption = NULL;
+
+    for (std::vector<Option *>::const_iterator i = options.begin(); i != options.end(); 
+            ++i) {
+        if (pos == 1) {
+            if (option[0] == (*i)->shortOption()[0]) {
+                theOption = (*i);
+            }
+        } else {
+            /* pos == 2 : todo - prefix matches */
+
+            if (option.find((*i)->longOption()) == 0) {
+                theOption = (*i);
+            }
+        }
     }
-  if (optCount == 0)
-    {
-//      log (LOG_TIMESTAMP,
-//        "%d Command line options passed, and no options registered\n",
-//        argc);
-      return false;
+    return theOption;
+}
+
+bool
+OptionSet::doNoArgumentOption(std::string &option, std::string::size_type const &pos)
+{
+    if (pos == 1 && option.size() > 1) {
+       /* Parameter when none allowed */
+       
+       if (option.find("=") == 1)
+           /* How best to provide failure state ? */
+           return false;
+       
+       argv.insert(argv.begin() + 1,"-" + option.substr(1));
     }
-//  log (LOG_TIMESTAMP, "Process command line options\n");
-  struct option longopts[optCount + 1];
-  String
-    shortopts;
-  for (int i = 0; i < optCount; ++i)
-    {
-      Option *anOption = options[i];
-      shortopts += anOption->shortOption ();
-      longopts[i] = anOption->longOption ();
+    
+    if (pos == 2) {
+       if (option.find("=") != string::npos)
+           /* How best to provide failure state ? */
+           return false;
     }
-  char const *
-    opts = shortopts.c_str ();
-  {
-    struct option
-      foo = {
-       0,
-       0,
-       0,
-    0 };
-    longopts[optCount] = foo;
-  }
-// where is this correctly defined?  opterr=0;
-  int lastoption;
-  while ((lastoption = getopt_long (argc, argv, opts, longopts, 0)) != -1)
-    {
-      if (lastoption)
-       {
-         if (lastoption == '\?')
-           {
-             //ambigous option  
-#if HAVE_STRING___H
-             delete[]opts;
-#endif
-             return false;
+    return true;
+}
+
+/* TODO: factor this better */
+void
+OptionSet::doOption(string &option, string::size_type const &pos)
+{
+    lastResult = Option::Failed;
+    option.erase(0, pos);
+    Option *theOption = findOption(option, pos);
+    char const *optionValue = NULL;
+    string value;
+
+    if (theOption == NULL)
+       return;
+
+    switch (theOption->argument()) {
+
+    case Option::None:
+        if (!doNoArgumentOption (option, pos))
+           return;
+       break;
+
+    case Option::Optional: {
+            if (pos == 1) {
+                if (option.size() == 1) {
+                    /* Value in next argv */
+
+                    if (argv.size() > 1) {
+                        string::size_type maybepos = argv[1].find_first_not_of("-");
+
+                        if (!isOption(maybepos))
+                            /* not an option */
+                            value = argv[1];
+                           argv.erase(argv.begin() + 1);
+                    }
+                } else {
+                    /* value if present is in this argv */
+
+                    if (option.find ("=") == 1) {
+                        /* option present */
+                        value = option.substr(2);
+                    } else
+                        /* no option present */
+                        argv.insert(argv.begin() + 1,"-" + option.substr(1));
+                }
+            }
+
+            if (pos == 2) {
+                string::size_type vpos = option.find("=");
+
+                if (vpos != string::npos) {
+                    /* How best to provide failure state ? */
+
+                    if (vpos == option.size() - 1)
+                        /* blank value */
+                       return;
+
+                    value = option.substr(vpos + 1);
+                } else {
+                    /* Value in next argv */
+
+                    if (argv.size() > 1) {
+                        string::size_type maybepos = argv[1].find_first_not_of("-");
+
+                        if (!isOption(maybepos))
+                            value = argv[1];
+                           argv.erase(argv.begin() + 1);
+                    }
+                }
+            }
+
+            if (value.size()) {
+               optionValue = value.c_str();
            }
-         for (int i = 0; i < optCount; ++i)
-           {
-             if (longopts[i].val == lastoption && !longopts[i].flag)
-               options[i]->Process (optarg);
+
+        }
+       break;
+
+    case Option::Required: {
+            if (pos == 1) {
+                if (option.size() == 1) {
+                    /* Value in next argv */
+
+                    if (argv.size() < 2)
+                        /* but there aren't any */
+                       return;
+
+                    string::size_type maybepos = argv[1].find_first_not_of("-");
+
+                    if (isOption(maybepos))
+                        /* The next argv is an option */
+                       return;
+
+                    value = argv[1]; 
+                   argv.erase(argv.begin() + 1);
+                } else {
+                    if (option.find ("=") != 1 || option.size() < 3)
+                        /* no option passed */
+                       return;
+
+                    value = option.substr(2);
+                }
+
+                argv.insert(argv.begin() + 1,"-" + option.substr(1));
+            }
+
+            if (pos == 2) {
+                string::size_type vpos = option.find("=");
+
+                if (vpos != string::npos) {
+                    /* How best to provide failure state ? */
+
+                    if (vpos == option.size() - 1)
+                       return;
+
+                    value = option.substr(vpos + 1);
+                } else {
+                    /* Value in next argv */
+
+                    if (argv.size() < 2)
+                        /* but there aren't any */
+                       return;
+
+                    string::size_type maybepos = argv[1].find_first_not_of("-");
+
+                    if (isOption(maybepos))
+                        /* The next argv is an option */
+                       return;
+
+                    value = argv[1];
+                   argv.erase(argv.begin() + 1);
+                }
+            } 
+           
+           optionValue = value.c_str();
+        }
+       break;
+    } 
+    lastResult = theOption->Process(optionValue);
+}
+
+OptionSet::OptionSet () {}
+
+OptionSet::~OptionSet ()
+{}
+
+void
+OptionSet::Init()
+{
+    options       = std::vector<Option *> ();
+    argv          = std::vector<string> ();
+    nonoptions    = std::vector<string> ();
+    remainingargv = std::vector<string> ();
+    nonOptionHandler = NULL;
+}
+
+bool
+OptionSet::process (Option *aNonOptionHandler)
+{
+    nonOptionHandler = aNonOptionHandler;
+    if (options.size() == 0 && nonOptionHandler == NULL)
+        return false;
+
+    while (argv.size()) {
+       processOne();
+        switch (lastResult) {
+
+        case Option::Failed:
+            return false;
+
+        case Option::Ok:
+            argv.erase(argv.begin());
+            break;
+
+        case Option::Stop:
+           if (argv.size() > 1) {
+               // dies: copy(argv.begin() + 1, argv.end(), remainingargv.begin()); 
+               for (std::vector<string>::iterator i = argv.begin() + 1; i != argv.end(); ++i)
+                   remainingargv.push_back(*i);
            }
-       }
+            return true;
+        }
     }
-    if (optind < argc && optind > 0 && defaultOptionSet)
-      return defaultOptionSet->Process (argc - optind, &argv[optind]);
-#if HAVE_STRING___H
-  delete[]opts;
-#endif
-  return true;
+
+    return true;
+}
+
+bool
+OptionSet::Process (int argc, char **argV, Option *nonOptionHandler)
+{
+    if (argc == 1) {
+        return true;
+    }
+
+    argv.clear();
+    nonoptions.clear();
+    remainingargv.clear();
+
+    for (int counter = 1; counter < argc; ++counter)
+        argv.push_back(string(argV[counter]));
+
+    return process(nonOptionHandler);
+}
+
+bool
+OptionSet::Process (std::vector<std::string> const &parms, Option *nonOptionHandler)
+{
+    if (parms.size() == 0)
+       return true;
+    argv = parms;
+    nonoptions.clear();
+    remainingargv.clear();
+    return process(nonOptionHandler);
 }
 
 //FIXME: check for conflicts.
 void
 OptionSet::Register (Option * anOption)
 {
-  Option **t = new Option *[optCount + 1];
-  for (int i = 0; i < optCount; ++i)
-    t[i] = options[i];
-  t[optCount++] = anOption;
-  delete[]options;
-  options = t;
+    options.push_back(anOption);
 }
 
-/* Show the options on the left, the short description on the right.
- * descriptions must be < 40 characters in length
- */
 void
 OptionSet::ParameterUsage (ostream &aStream)
 {
-  for (int i = 0; i < optCount; ++i)
-    {
-      Option *anOption = options[i];
-      String output = String() + " -" + anOption->shortOption ()[0];
-      output += " --" ;
-      output += anOption->longOption ().name;
-      output += String (40 - output.size(), ' ');
-      output += anOption->shortHelp();
-      aStream << output << endl;
-    }
+    for_each (options.begin(), options.end(), DefaultFormatter (aStream));
+}
+
+std::vector<Option *> const &
+OptionSet::optionsInSet() const
+{
+    return options;
+}
+
+std::vector<string> const &
+OptionSet::nonOptions() const
+{
+    return nonoptions;
+}
+
+std::vector<string> const &
+OptionSet::remainingArgv() const
+{
+    return remainingargv;
 }
This page took 0.031786 seconds and 5 git commands to generate.