/*
 * AnyOption 1.3
 *
 * kishan at hackorama dot com  www.hackorama.com JULY 2001
 *
 * + Acts as a common facade class for reading
 *   commandline options as well as options from
 *   an optionfile with delimited type value pairs
 *
 * + Handles the POSIX style single character options ( -w )
 *   as well as the newer GNU long options ( --width )
 *
 * + The option file assumes the traditional format of
 *   first character based comment lines and type value
 *   pairs with a delimiter , and flags which are not pairs
 *
 *  	# this is a coment
 *  	# next line is an option value pair
 *  	width : 100
 *     	# next line is a flag
 *      noimages
 *
 * + Supports printing out Help and Usage
 *
 * + Why not just use getopt() ?
 *
 *   getopt() Its a POSIX standard not part of ANSI-C.
 *   So it may not be available on platforms like Windows.
 *
 * + Why it is so long ?
 *
 *   The actual code which does command line parsing
 *   and option file parsing are done in  few methods.
 *   Most of the extra code are for providing a flexible
 *   common public interface to both a resourcefile and
 *   and command line supporting POSIX style and
 *   GNU long option as well as mixing of both.
 *
 * + Please see "anyoption.h" for public method descriptions
 *
 */

/* Updated Auguest 2004
 * Fix from  Michael D Peters (mpeters at sandia.gov)
 * to remove static local variables, allowing multiple instantiations
 * of the reader (for using multiple configuration files).  There is
 * an error in the destructor when using multiple instances, so you
 * cannot delete your objects (it will crash), but not calling the
 * destructor only introduces a small memory leak, so I
 * have not bothered tracking it down.
 *
 * Also updated to use modern C++ style headers, rather than
 * depricated iostream.h (it was causing my compiler problems)
*/

/*
 * Updated September 2006
 * Fix from Boyan Asenov for a bug in mixing up option indexes
 * leading to exception when mixing different options types
 */

#include "anyoption.h"
#include <cstring>

AnyOption::AnyOption () { init (); }

AnyOption::AnyOption (int maxopt) { init (maxopt, maxopt); }

AnyOption::AnyOption (int maxopt, int maxcharopt) { init (maxopt, maxcharopt); }

AnyOption::~AnyOption () {
        if (mem_allocated)
                cleanup ();
}

void AnyOption::init () { init (DEFAULT_MAXOPTS, DEFAULT_MAXOPTS); }

void AnyOption::init (int maxopt, int maxcharopt) {

        max_options = maxopt;
        max_char_options = maxcharopt;
        max_usage_lines = DEFAULT_MAXUSAGE;
        usage_lines = 0;
        argc = 0;
        argv = NULL;
        posix_style = true;
        verbose = false;
        filename = NULL;
        appname = NULL;
        option_counter = 0;
        optchar_counter = 0;
        new_argv = NULL;
        new_argc = 0;
        max_legal_args = 0;
        command_set = false;
        file_set = false;
        values = NULL;
        g_value_counter = 0;
        mem_allocated = false;
        command_set = false;
        file_set = false;
        opt_prefix_char = '-';
        file_delimiter_char = ':';
        file_comment_char = '#';
        equalsign = '=';
        comment = '#';
        delimiter = ':';
        endofline = '\n';
        whitespace = ' ';
        nullterminate = '\0';
        set = false;
        once = true;
        hasoptions = false;
        autousage = false;

        strcpy (long_opt_prefix, "--");

        if (alloc () == false) {
                cout << endl << "OPTIONS ERROR : Failed allocating memory";
                cout << endl;
                cout << "Exiting." << endl;
                throw;
        }
}

bool AnyOption::alloc () {
        int i = 0;
        int size = 0;

        if (mem_allocated)
                return true;

        size = (max_options + 1) * sizeof (const char *);
        options = (const char **)malloc (size);
        optiontype = (int *)malloc ((max_options + 1) * sizeof (int));
        optionindex = (int *)malloc ((max_options + 1) * sizeof (int));
        if (options == NULL || optiontype == NULL || optionindex == NULL)
                return false;
        else
                mem_allocated = true;
        for (i = 0; i < max_options; i++) {
                options[i] = NULL;
                optiontype[i] = 0;
                optionindex[i] = -1;
        }
        optionchars = (char *)malloc ((max_char_options + 1) * sizeof (char));
        optchartype = (int *)malloc ((max_char_options + 1) * sizeof (int));
        optcharindex = (int *)malloc ((max_char_options + 1) * sizeof (int));
        if (optionchars == NULL || optchartype == NULL || optcharindex == NULL) {
                mem_allocated = false;
                return false;
        }
        for (i = 0; i < max_char_options; i++) {
                optionchars[i] = '0';
                optchartype[i] = 0;
                optcharindex[i] = -1;
        }

        size = (max_usage_lines + 1) * sizeof (const char *);
        // usage = (const char**) malloc( size );

        // if( usage == NULL  ){
        //	mem_allocated = false;
        //	return false;
        //}
        // for( i = 0 ; i < max_usage_lines ; i++ )
        //	usage[i] = NULL;

        return true;
}

bool AnyOption::doubleOptStorage () {
        options = (const char **)realloc (options, ((2 * max_options) + 1) * sizeof (const char *));
        optiontype = (int *)realloc (optiontype, ((2 * max_options) + 1) * sizeof (int));
        optionindex = (int *)realloc (optionindex, ((2 * max_options) + 1) * sizeof (int));
        if (options == NULL || optiontype == NULL || optionindex == NULL)
                return false;
        /* init new storage */
        for (int i = max_options; i < 2 * max_options; i++) {
                options[i] = NULL;
                optiontype[i] = 0;
                optionindex[i] = -1;
        }
        max_options = 2 * max_options;
        return true;
}

bool AnyOption::doubleCharStorage () {
        optionchars = (char *)realloc (optionchars, ((2 * max_char_options) + 1) * sizeof (char));
        optchartype = (int *)realloc (optchartype, ((2 * max_char_options) + 1) * sizeof (int));
        optcharindex = (int *)realloc (optcharindex, ((2 * max_char_options) + 1) * sizeof (int));
        if (optionchars == NULL || optchartype == NULL || optcharindex == NULL)
                return false;
        /* init new storage */
        for (int i = max_char_options; i < 2 * max_char_options; i++) {
                optionchars[i] = '0';
                optchartype[i] = 0;
                optcharindex[i] = -1;
        }
        max_char_options = 2 * max_char_options;
        return true;
}

void AnyOption::cleanup () {
        free (options);
        free (optiontype);
        free (optionindex);
        free (optionchars);
        free (optchartype);
        free (optcharindex);
        // free (usage);
        for (int i = 0; i < g_value_counter; i++) {
                if (values[i] != NULL)
                        free (values[i]);
        }
        if (values != NULL)
                free (values);
        if (new_argv != NULL)
                free (new_argv);
}

void AnyOption::setCommandPrefixChar (char _prefix) { opt_prefix_char = _prefix; }

void AnyOption::setCommandLongPrefix (char *_prefix) {
        if (strlen (_prefix) > MAX_LONG_PREFIX_LENGTH) {
                *(_prefix + MAX_LONG_PREFIX_LENGTH) = '\0';
        }

        strcpy (long_opt_prefix, _prefix);
}

void AnyOption::setFileCommentChar (char _comment) { file_delimiter_char = _comment; }

void AnyOption::setFileDelimiterChar (char _delimiter) { file_comment_char = _delimiter; }

bool AnyOption::CommandSet () { return (command_set); }

bool AnyOption::FileSet () { return (file_set); }

void AnyOption::noPOSIX () { posix_style = false; }

bool AnyOption::POSIX () { return posix_style; }

void AnyOption::setVerbose () { verbose = true; }

void AnyOption::printVerbose () {
        if (verbose)
                cout << endl;
}
void AnyOption::printVerbose (const char *msg) {
        if (verbose)
                cout << msg;
}

void AnyOption::printVerbose (char *msg) {
        if (verbose)
                cout << msg;
}

void AnyOption::printVerbose (char ch) {
        if (verbose)
                cout << ch;
}

bool AnyOption::hasOptions () { return hasoptions; }

void AnyOption::autoUsagePrint (bool _autousage) { autousage = _autousage; }

void AnyOption::useCommandArgs (int _argc, char **_argv) {
        argc = _argc;
        argv = _argv;
        command_set = true;
        appname = argv[0];
        if (argc > 1)
                hasoptions = true;
}

void AnyOption::useFileName (const char *_filename) {
        filename = _filename;
        file_set = true;
}

/*
 * set methods for options
 */

void AnyOption::setCommandOption (const char *opt) {
        addOption (opt, COMMAND_OPT);
        g_value_counter++;
}

void AnyOption::setCommandOption (char opt) {
        addOption (opt, COMMAND_OPT);
        g_value_counter++;
}

void AnyOption::setCommandOption (const char *opt, char optchar) {
        addOption (opt, COMMAND_OPT);
        addOption (optchar, COMMAND_OPT);
        g_value_counter++;
}

void AnyOption::setCommandFlag (const char *opt) {
        addOption (opt, COMMAND_FLAG);
        g_value_counter++;
}

void AnyOption::setCommandFlag (char opt) {
        addOption (opt, COMMAND_FLAG);
        g_value_counter++;
}

void AnyOption::setCommandFlag (const char *opt, char optchar) {
        addOption (opt, COMMAND_FLAG);
        addOption (optchar, COMMAND_FLAG);
        g_value_counter++;
}

void AnyOption::setFileOption (const char *opt) {
        addOption (opt, FILE_OPT);
        g_value_counter++;
}

void AnyOption::setFileOption (char opt) {
        addOption (opt, FILE_OPT);
        g_value_counter++;
}

void AnyOption::setFileOption (const char *opt, char optchar) {
        addOption (opt, FILE_OPT);
        addOption (optchar, FILE_OPT);
        g_value_counter++;
}

void AnyOption::setFileFlag (const char *opt) {
        addOption (opt, FILE_FLAG);
        g_value_counter++;
}

void AnyOption::setFileFlag (char opt) {
        addOption (opt, FILE_FLAG);
        g_value_counter++;
}

void AnyOption::setFileFlag (const char *opt, char optchar) {
        addOption (opt, FILE_FLAG);
        addOption (optchar, FILE_FLAG);
        g_value_counter++;
}

void AnyOption::setOption (const char *opt) {
        addOption (opt, COMMON_OPT);
        g_value_counter++;
}

void AnyOption::setOption (char opt) {
        addOption (opt, COMMON_OPT);
        g_value_counter++;
}

void AnyOption::setOption (const char *opt, char optchar) {
        addOption (opt, COMMON_OPT);
        addOption (optchar, COMMON_OPT);
        g_value_counter++;
}

void AnyOption::setFlag (const char *opt) {
        addOption (opt, COMMON_FLAG);
        g_value_counter++;
}

void AnyOption::setFlag (const char opt) {
        addOption (opt, COMMON_FLAG);
        g_value_counter++;
}

void AnyOption::setFlag (const char *opt, char optchar) {
        addOption (opt, COMMON_FLAG);
        addOption (optchar, COMMON_FLAG);
        g_value_counter++;
}

void AnyOption::addOption (const char *opt, int type) {
        if (option_counter >= max_options) {
                if (doubleOptStorage () == false) {
                        addOptionError (opt);
                        return;
                }
        }
        options[option_counter] = opt;
        optiontype[option_counter] = type;
        optionindex[option_counter] = g_value_counter;
        option_counter++;
}

void AnyOption::addOption (char opt, int type) {
        if (!POSIX ()) {
                printVerbose ("Ignoring the option character \"");
                printVerbose (opt);
                printVerbose ("\" ( POSIX options are turned off )");
                printVerbose ();
                return;
        }

        if (optchar_counter >= max_char_options) {
                if (doubleCharStorage () == false) {
                        addOptionError (opt);
                        return;
                }
        }
        optionchars[optchar_counter] = opt;
        optchartype[optchar_counter] = type;
        optcharindex[optchar_counter] = g_value_counter;
        optchar_counter++;
}

void AnyOption::addOptionError (const char *opt) {
        cout << endl;
        cout << "OPTIONS ERROR : Failed allocating extra memory " << endl;
        cout << "While adding the option : \"" << opt << "\"" << endl;
        cout << "Exiting." << endl;
        cout << endl;
        throw;
}

void AnyOption::addOptionError (char opt) {
        cout << endl;
        cout << "OPTIONS ERROR : Failed allocating extra memory " << endl;
        cout << "While adding the option: \"" << opt << "\"" << endl;
        cout << "Exiting." << endl;
        cout << endl;
        throw;
}

void AnyOption::processOptions () {
        if (!valueStoreOK ())
                return;
}

void AnyOption::processCommandArgs (int max_args) {
        max_legal_args = max_args;
        processCommandArgs ();
}

void AnyOption::processCommandArgs (int _argc, char **_argv, int max_args) {
        max_legal_args = max_args;
        processCommandArgs (_argc, _argv);
}

void AnyOption::processCommandArgs (int _argc, char **_argv) {
        useCommandArgs (_argc, _argv);
        processCommandArgs ();
}

void AnyOption::processCommandArgs () {
        if (!(valueStoreOK () && CommandSet ()))
                return;

        if (max_legal_args == 0)
                max_legal_args = argc;
        new_argv = (int *)malloc ((max_legal_args + 1) * sizeof (int));
        for (int i = 1; i < argc; i++) {                                                    /* ignore first argv */
                if (argv[i][0] == long_opt_prefix[0] && argv[i][1] == long_opt_prefix[1]) { /* long GNU option */
                        int match_at = parseGNU (argv[i] + 2);                              /* skip -- */
                        if (match_at >= 0 && i < argc - 1)                                  /* found match */
                                setValue (options[match_at], argv[++i]);
                } else if (argv[i][0] == opt_prefix_char) { /* POSIX char */
                        if (POSIX ()) {
                                char ch = parsePOSIX (argv[i] + 1); /* skip - */
                                if (ch != '0' && i < argc - 1)      /* matching char */
                                        setValue (ch, argv[++i]);
                        } else {                                       /* treat it as GNU option with a - */
                                int match_at = parseGNU (argv[i] + 1); /* skip - */
                                if (match_at >= 0 && i < argc - 1)     /* found match */
                                        setValue (options[match_at], argv[++i]);
                        }
                } else { /* not option but an argument keep index */
                        if (new_argc < max_legal_args) {
                                new_argv[new_argc] = i;
                                new_argc++;
                        } else { /* ignore extra arguments */
                                printVerbose ("Ignoring extra argument: ");
                                printVerbose (argv[i]);
                                printVerbose ();
                                printAutoUsage ();
                        }
                        printVerbose ("Unknown command argument option : ");
                        printVerbose (argv[i]);
                        printVerbose ();
                        printAutoUsage ();
                }
        }
}

char AnyOption::parsePOSIX (char *arg) {

        for (unsigned int i = 0; i < strlen (arg); i++) {
                char ch = arg[i];
                if (matchChar (ch)) { /* keep matching flags till an option */
                        /*if last char argv[++i] is the value */
                        if (i == strlen (arg) - 1) {
                                return ch;
                        } else {     /* else the rest of arg is the value */
                                i++; /* skip any '=' and ' ' */
                                while (arg[i] == whitespace || arg[i] == equalsign)
                                        i++;
                                setValue (ch, arg + i);
                                return '0';
                        }
                }
        }
        printVerbose ("Unknown command argument option : ");
        printVerbose (arg);
        printVerbose ();
        printAutoUsage ();
        return '0';
}

int AnyOption::parseGNU (char *arg) {
        int split_at = 0;
        /* if has a '=' sign get value */
        for (unsigned int i = 0; i < strlen (arg); i++) {
                if (arg[i] == equalsign) {
                        split_at = i;     /* store index */
                        i = strlen (arg); /* get out of loop */
                }
        }
        if (split_at > 0) { /* it is an option value pair */
                char *tmp = (char *)malloc ((split_at + 1) * sizeof (char));
                for (int i = 0; i < split_at; i++)
                        tmp[i] = arg[i];
                tmp[split_at] = '\0';

                if (matchOpt (tmp) >= 0) {
                        setValue (options[matchOpt (tmp)], arg + split_at + 1);
                        free (tmp);
                } else {
                        printVerbose ("Unknown command argument option : ");
                        printVerbose (arg);
                        printVerbose ();
                        printAutoUsage ();
                        free (tmp);
                        return -1;
                }
        } else { /* regular options with no '=' sign  */
                return matchOpt (arg);
        }
        return -1;
}

int AnyOption::matchOpt (char *opt) {
        for (int i = 0; i < option_counter; i++) {
                if (strcmp (options[i], opt) == 0) {
                        if (optiontype[i] == COMMON_OPT || optiontype[i] == COMMAND_OPT) {
                                /* found option return index */
                                return i;
                        } else if (optiontype[i] == COMMON_FLAG || optiontype[i] == COMMAND_FLAG) {
                                /* found flag, set it */
                                setFlagOn (opt);
                                return -1;
                        }
                }
        }
        printVerbose ("Unknown command argument option : ");
        printVerbose (opt);
        printVerbose ();
        printAutoUsage ();
        return -1;
}
bool AnyOption::matchChar (char c) {
        for (int i = 0; i < optchar_counter; i++) {
                if (optionchars[i] == c) { /* found match */
                        if (optchartype[i] == COMMON_OPT || optchartype[i] == COMMAND_OPT) {
                                /* an option store and stop scanning */
                                return true;
                        } else if (optchartype[i] == COMMON_FLAG ||
                                   optchartype[i] == COMMAND_FLAG) { /* a flag store and keep scanning */
                                setFlagOn (c);
                                return false;
                        }
                }
        }
        printVerbose ("Unknown command argument option : ");
        printVerbose (c);
        printVerbose ();
        printAutoUsage ();
        return false;
}

bool AnyOption::valueStoreOK () {
        int size = 0;
        if (!set) {
                if (g_value_counter > 0) {
                        size = g_value_counter * sizeof (char *);
                        values = (char **)malloc (size);
                        for (int i = 0; i < g_value_counter; i++)
                                values[i] = NULL;
                        set = true;
                }
        }
        return set;
}

/*
 * public get methods
 */
char *AnyOption::getValue (const char *option) {
        if (!valueStoreOK ())
                return NULL;

        for (int i = 0; i < option_counter; i++) {
                if (strcmp (options[i], option) == 0)
                        return values[optionindex[i]];
        }
        return NULL;
}

bool AnyOption::getFlag (const char *option) {
        if (!valueStoreOK ())
                return false;
        for (int i = 0; i < option_counter; i++) {
                if (strcmp (options[i], option) == 0)
                        return findFlag (values[optionindex[i]]);
        }
        return false;
}

char *AnyOption::getValue (char option) {
        if (!valueStoreOK ())
                return NULL;
        for (int i = 0; i < optchar_counter; i++) {
                if (optionchars[i] == option)
                        return values[optcharindex[i]];
        }
        return NULL;
}

bool AnyOption::getFlag (char option) {
        if (!valueStoreOK ())
                return false;
        for (int i = 0; i < optchar_counter; i++) {
                if (optionchars[i] == option)
                        return findFlag (values[optcharindex[i]]);
        }
        return false;
}

bool AnyOption::findFlag (char *val) {
        if (val == NULL)
                return false;

        if (strcmp (TRUE_FLAG, val) == 0)
                return true;

        return false;
}

/*
 * private set methods
 */
bool AnyOption::setValue (const char *option, char *value) {
        if (!valueStoreOK ())
                return false;
        for (int i = 0; i < option_counter; i++) {
                if (strcmp (options[i], option) == 0) {
                        values[optionindex[i]] = (char *)malloc ((strlen (value) + 1) * sizeof (char));
                        strcpy (values[optionindex[i]], value);
                        return true;
                }
        }
        return false;
}

bool AnyOption::setFlagOn (const char *option) {
        if (!valueStoreOK ())
                return false;
        for (int i = 0; i < option_counter; i++) {
                if (strcmp (options[i], option) == 0) {
                        values[optionindex[i]] = (char *)malloc ((strlen (TRUE_FLAG) + 1) * sizeof (char));
                        strcpy (values[optionindex[i]], TRUE_FLAG);
                        return true;
                }
        }
        return false;
}

bool AnyOption::setValue (char option, char *value) {
        if (!valueStoreOK ())
                return false;
        for (int i = 0; i < optchar_counter; i++) {
                if (optionchars[i] == option) {
                        values[optcharindex[i]] = (char *)malloc ((strlen (value) + 1) * sizeof (char));
                        strcpy (values[optcharindex[i]], value);
                        return true;
                }
        }
        return false;
}

bool AnyOption::setFlagOn (char option) {
        if (!valueStoreOK ())
                return false;
        for (int i = 0; i < optchar_counter; i++) {
                if (optionchars[i] == option) {
                        values[optcharindex[i]] = (char *)malloc ((strlen (TRUE_FLAG) + 1) * sizeof (char));
                        strcpy (values[optcharindex[i]], TRUE_FLAG);
                        return true;
                }
        }
        return false;
}

int AnyOption::getArgc () { return new_argc; }

char *AnyOption::getArgv (int index) {
        if (index < new_argc) {
                return (argv[new_argv[index]]);
        }
        return NULL;
}

/* dotfile sub routines */

bool AnyOption::processFile () {
        if (!(valueStoreOK () && FileSet ()))
                return false;
        return (consumeFile (readFile ()));
}

bool AnyOption::processFile (const char *filename) {
        useFileName (filename);
        return (processFile ());
}

char *AnyOption::readFile () { return (readFile (filename)); }

/*
 * read the file contents to a character buffer
 */

char *AnyOption::readFile (const char *fname) {
        int length;
        char *buffer;
        ifstream is;
        is.open (fname, ifstream::in);
        if (!is.good ()) {
                is.close ();
                return NULL;
        }
        is.seekg (0, ios::end);
        length = is.tellg ();
        is.seekg (0, ios::beg);
        buffer = (char *)malloc (length * sizeof (char));
        is.read (buffer, length);
        is.close ();
        return buffer;
}

/*
 * scans a char* buffer for lines that does not
 * start with the specified comment character.
 */
bool AnyOption::consumeFile (char *buffer) {

        if (buffer == NULL)
                return false;

        char *cursor = buffer; /* preserve the ptr */
        char *pline = NULL;
        int linelength = 0;
        bool newline = true;
        for (unsigned int i = 0; i < strlen (buffer); i++) {
                if (*cursor == endofline) { /* end of line */
                        if (pline != NULL)  /* valid line */
                                processLine (pline, linelength);
                        pline = NULL;
                        newline = true;
                } else if (newline) { /* start of line */
                        newline = false;
                        if ((*cursor != comment)) { /* not a comment */
                                pline = cursor;
                                linelength = 0;
                        }
                }
                cursor++; /* keep moving */
                linelength++;
        }
        free (buffer);
        return true;
}

/*
 *  find a valid type value pair separated by a delimiter
 *  character and pass it to valuePairs()
 *  any line which is not valid will be considered a value
 *  and will get passed on to justValue()
 *
 *  assuming delimiter is ':' the behaviour will be,
 *
 *  width:10    - valid pair valuePairs( width, 10 );
 *  width : 10  - valid pair valuepairs( width, 10 );
 *
 *  ::::        - not valid
 *  width       - not valid
 *  :10         - not valid
 *  width:      - not valid
 *  ::          - not valid
 *  :           - not valid
 *
 */

void AnyOption::processLine (char *theline, int length) {
        bool found = false;
        char *pline = (char *)malloc ((length + 1) * sizeof (char));
        for (int i = 0; i < length; i++)
                pline[i] = *(theline++);
        pline[length] = nullterminate;
        char *cursor = pline; /* preserve the ptr */
        if (*cursor == delimiter || *(cursor + length - 1) == delimiter) {
                justValue (pline); /* line with start/end delimiter */
        } else {
                for (int i = 1; i < length - 1 && !found; i++) { /* delimiter */
                        if (*cursor == delimiter) {
                                *(cursor - 1) = nullterminate; /* two strings */
                                found = true;
                                valuePairs (pline, cursor + 1);
                        }
                        cursor++;
                }
                cursor++;
                if (!found) /* not a pair */
                        justValue (pline);
        }
        free (pline);
}

/*
 * removes trailing and preceeding whitespaces from a string
 */
char *AnyOption::chomp (char *str) {
        while (*str == whitespace)
                str++;
        char *end = str + strlen (str) - 1;
        while (*end == whitespace)
                end--;
        *(end + 1) = nullterminate;
        return str;
}

void AnyOption::valuePairs (char *type, char *value) {
        if (strlen (chomp (type)) == 1) { /* this is a char option */
                for (int i = 0; i < optchar_counter; i++) {
                        if (optionchars[i] == type[0]) { /* match */
                                if (optchartype[i] == COMMON_OPT || optchartype[i] == FILE_OPT) {
                                        setValue (type[0], chomp (value));
                                        return;
                                }
                        }
                }
        }
        /* if no char options matched */
        for (int i = 0; i < option_counter; i++) {
                if (strcmp (options[i], type) == 0) { /* match */
                        if (optiontype[i] == COMMON_OPT || optiontype[i] == FILE_OPT) {
                                setValue (type, chomp (value));
                                return;
                        }
                }
        }
        printVerbose ("Unknown option in resourcefile : ");
        printVerbose (type);
        printVerbose ();
}

void AnyOption::justValue (char *type) {

        if (strlen (chomp (type)) == 1) { /* this is a char option */
                for (int i = 0; i < optchar_counter; i++) {
                        if (optionchars[i] == type[0]) { /* match */
                                if (optchartype[i] == COMMON_FLAG || optchartype[i] == FILE_FLAG) {
                                        setFlagOn (type[0]);
                                        return;
                                }
                        }
                }
        }
        /* if no char options matched */
        for (int i = 0; i < option_counter; i++) {
                if (strcmp (options[i], type) == 0) { /* match */
                        if (optiontype[i] == COMMON_FLAG || optiontype[i] == FILE_FLAG) {
                                setFlagOn (type);
                                return;
                        }
                }
        }
        printVerbose ("Unknown option in resourcefile : ");
        printVerbose (type);
        printVerbose ();
}

/*
 * usage and help
 */

void AnyOption::printAutoUsage () {
        if (autousage)
                printUsage ();
}

void AnyOption::printUsage () {

        if (once) {
                once = false;
                cout << endl;
                for (int i = 0; i < usage_lines; i++)
                        cout << usage[i] << endl;
                cout << endl;
        }
}

void AnyOption::addUsage (const std::string line) { this->addUsage (line.c_str ()); }

void AnyOption::addUsage (const char *line) {
        // 	if( usage_lines >= max_usage_lines ){
        // 		if( doubleUsageStorage() == false ){
        // 			addUsageError( line );
        // 			exit(1);
        // 		}
        // 	}
        std::string s;
        s = line;
        usage.push_back (s);
        usage_lines++;
}

void AnyOption::addUsageError (const char *line) {
        cout << endl;
        cout << "OPTIONS ERROR : Failed allocating extra memory " << endl;
        cout << "While adding the usage/help  : \"" << line << "\"" << endl;
        cout << "Exiting." << endl;
        cout << endl;
        throw;
}
