<commit_before>/*
 * CommandLineOptions.cpp
 *
 *  Created on: Feb 15, 2011
 *      Author: <NAME>
 *     Version: $Id$
 *
 * Copyright 2011 <NAME>, all rights reserved.
 */

#ifndef FLTL_COMMANDLINEOPTIONS_CPP_
#define FLTL_COMMANDLINEOPTIONS_CPP_

#include "grail/include/CommandLineOptions.hpp"

namespace grail {

    namespace detail {
        static int iskeychar(int c) throw() {
            return isalnum(c) || '-' == c;
        }
        static const char *eat_chars(const char *start, int(*pred)(int)) throw() {
            for(; 0 != start && pred(*start); ++start) { }
            return start;
        }
        static size_t alpha_to_offset(char ch) throw() {
            if(ch >= 'a') {
                return size_t(ch - 'a');
            }
            return size_t(ch - 'A');
        }
    }

    namespace diag {

        // the code for a diagnostic. when diagnostics occur, they are
        // referenced with the diagnostic codes.
        enum {
#define DIAG(ENUM_NAME,_) ENUM_NAME,
#include "grail/lib/diag/CommandLineOptions.inc"
#undef DIAG
            __null_diagnostic__
        };

        // bring in the pre-processed diagnostic messages
        static const char *diag_message[] = {
#define DIAG(_,TEXT) TEXT,
#include "grail/lib/diag/CommandLineOptions.inc"
#undef DIAG
        };
    }

    CommandLineOption::CommandLineOption(void) throw()
        : opt_argv(-1)
        , val_argv(0)
        , opt_begin(0)
        , val_begin(0)
        , val_end(0)
        , is_positional(false)
        , is_positional_candidate(true)
        , is_accounted_for(false)
        , next(0)
    { }

    /// initialize the begin and end offsets for a command line option
    void CommandLineOption::init(const int val_argv_, const char *val_start) throw() {
        val_begin = val_start;
        val_end = val_start;
        val_argv = val_argv_;

        for(const char *end_next(val_end);
            0 != end_next && '\0' != *end_next;
            ++end_next) {

            if(!isspace(*end_next)) {
                val_end = end_next + 1;
            }
        }
    }

    /// constructor
    CommandLineOptions::CommandLineOptions(
        const int argc_,
        const char **argv_
    ) throw()
        : argc(argc_)
        , argv(argv_)
        , first(0)
        , last(0)
        , long_options()
        , has_errors(false)
        , num_positional(0)
    {
        memset(short_options, 0, sizeof(CommandLineOption *) * 52);
    }

    CommandLineOptions::~CommandLineOptions(void) throw() {
        for(CommandLineOption *curr(first), *next(0);
            0 != curr;
            curr = next) {

            next = curr->next;
            delete curr;
        }
        first = 0;
        last = 0;
    }

    CommandLineOption *CommandLineOptions::make_option(
        const int argv_offset,
        const char *first_char
    ) throw() {
        CommandLineOption *opt(new CommandLineOption);
        if(0 == first) {
            first = opt;
            last = opt;
        } else {
            last->next = opt;
            last = opt;
        }
        opt->opt_argv = argv_offset;
        opt->opt_begin = first_char;
        return opt;
    }

    /// parse the basic structure of command-line options
    bool CommandLineOptions::parse(void) throw() {

        CommandLineOption *opt_to_fill(0);
        bool opt_to_fill_is_long(false);
        const char *first_char(0);
        size_t equals_offset(0);
        int equals_argv(-1);

        for(int i(1); i < argc; ++i) {

            first_char = detail::eat_chars(
                &(argv[i][0]),
                &isspace
            );
            size_t offset(static_cast<size_t>(first_char - argv[i]));

        process_first_char:

            // all spaces
            if('\0' == *first_char) {
                continue;

            // keyword argument
            } else if('-' == *first_char) {
                opt_to_fill = 0;

                // long option
                if('-' == first_char[1]) {

                    if(!isalpha(first_char[2])) {
                        return error(diag::err_bad_long_option, i, offset + 2UL);
                    }

                    // go find the next non-alphabetic character
                    const char *next_char(detail::eat_chars(
                        &(first_char[2]),
                        &detail::iskeychar)
                    );

                    // assign the whole thing, then resize down; used to get
                    // around an annoying gcc 4.1.2 bug
                    std::string kw(&(first_char[2]));
                    kw.resize(static_cast<size_t>(
                        next_char - (first_char + 2)
                    ));

                    CommandLineOption *&opt(long_options[kw]);

                    if(0 != opt) {
                        error(diag::err_redefine_option, i, offset + 2UL);
                        note(
                            diag::note_prev_option_definition,
                            opt
                        );
                        return false;
                    }

                    // add in the option
                    opt = opt_to_fill = make_option(i, first_char + 2);
                    first_char = next_char;
                    opt_to_fill_is_long = true;
                    offset = 0;
                    goto process_first_char;

                // short option
                } else if(isalpha(first_char[1])){

                    // go fin the next non-space character
                    const char *next_char(detail::eat_chars(
                        &(first_char[2]),
                        &isspace
                    ));<commit_msg>working on a casting issue.. weird.<commit_after>/*
 * CommandLineOptions.cpp
 *
 *  Created on: Feb 15, 2011
 *      Author: <NAME>
 *     Version: $Id$
 *
 * Copyright 2011 <NAME>, all rights reserved.
 */

#ifndef FLTL_COMMANDLINEOPTIONS_CPP_
#define FLTL_COMMANDLINEOPTIONS_CPP_

#include "grail/include/CommandLineOptions.hpp"

namespace grail {

    namespace detail {
        static int iskeychar(int c) throw() {
            return isalnum(c) || '-' == c;
        }
        static const char *eat_chars(const char *start, int(*pred)(int)) throw() {
            for(; 0 != start && pred(*start); ++start) { }
            return start;
        }
        static size_t alpha_to_offset(char ch) throw() {
            if(ch >= 'a') {
                return size_t(ch - 'a');
            }
            return size_t(ch - 'A');
        }
    }

    namespace diag {

        // the code for a diagnostic. when diagnostics occur, they are
        // referenced with the diagnostic codes.
        enum {
#define DIAG(ENUM_NAME,_) ENUM_NAME,
#include "grail/lib/diag/CommandLineOptions.inc"
#undef DIAG
            __null_diagnostic__
        };

        // bring in the pre-processed diagnostic messages
        static const char *diag_message[] = {
#define DIAG(_,TEXT) TEXT,
#include "grail/lib/diag/CommandLineOptions.inc"
#undef DIAG
        };
    }

    CommandLineOption::CommandLineOption(void) throw()
        : opt_argv(-1)
        , val_argv(0)
        , opt_begin(0)
        , val_begin(0)
        , val_end(0)
        , is_positional(false)
        , is_positional_candidate(true)
        , is_accounted_for(false)
        , next(0)
    { }

    /// initialize the begin and end offsets for a command line option
    void CommandLineOption::init(const int val_argv_, const char *val_start) throw() {
        val_begin = val_start;
        val_end = val_start;
        val_argv = val_argv_;

        for(const char *end_next(val_end);
            0 != end_next && '\0' != *end_next;
            ++end_next) {

            if(!isspace(*end_next)) {
                val_end = end_next + 1;
            }
        }
    }

    /// constructor
    CommandLineOptions::CommandLineOptions(
        const int argc_,
        const char **argv_
    ) throw()
        : argc(argc_)
        , argv(argv_)
        , first(0)
        , last(0)
        , long_options()
        , has_errors(false)
        , num_positional(0)
    {
        memset(short_options, 0, sizeof(CommandLineOption *) * 52);
    }

    CommandLineOptions::~CommandLineOptions(void) throw() {
        for(CommandLineOption *curr(first), *next(0);
            0 != curr;
            curr = next) {

            next = curr->next;
            delete curr;
        }
        first = 0;
        last = 0;
    }

    CommandLineOption *CommandLineOptions::make_option(
        const int argv_offset,
        const char *first_char
    ) throw() {
        CommandLineOption *opt(new CommandLineOption);
        if(0 == first) {
            first = opt;
            last = opt;
        } else {
            last->next = opt;
            last = opt;
        }
        opt->opt_argv = argv_offset;
        opt->opt_begin = first_char;
        return opt;
    }

    /// parse the basic structure of command-line options
    bool CommandLineOptions::parse(void) throw() {

        CommandLineOption *opt_to_fill(0);
        bool opt_to_fill_is_long(false);
        const char *first_char(0);
        size_t equals_offset(0);
        int equals_argv(-1);

        for(int i(1); i < argc; ++i) {

            first_char = detail::eat_chars(
                &(argv[i][0]),
                &isspace
            );
            size_t offset(static_cast<size_t>(first_char - argv[i]));

        process_first_char:

            // all spaces
            if('\0' == *first_char) {
                continue;

            // keyword argument
            } else if('-' == *first_char) {
                opt_to_fill = 0;

                // long option
                if('-' == first_char[1]) {

                    if(!isalpha(first_char[2])) {
                        return error(diag::err_bad_long_option, i, offset + 2UL);
                    }

                    // go find the next non-alphabetic character
                    const char *next_char(detail::eat_chars(
                        &(first_char[2]),
                        &detail::iskeychar)
                    );

                    // assign the whole thing, then resize down; used to get
                    // around an annoying gcc 4.1.2 bug
                    std::string kw(&(first_char[2]));
                    //,
                    //    static_cast<size_t>(next_char - (first_char + 2))
                    //);

                    CommandLineOption *&opt(long_options[kw]);

                    if(0 != opt) {
                        error(diag::err_redefine_option, i, offset + 2UL);
                        note(
                            diag::note_prev_option_definition,
                            opt
                        );
                        return false;
                    }

                    // add in the option
                    opt = opt_to_fill = make_option(i, first_char + 2);
                    first_char = next_char;
                    opt_to_fill_is_long = true;
                    offset = 0;
                    goto process_first_char;

                // short option
                } else if(isalpha(first_char[1])){

                    // go fin the next non-space character
                    const char *next_char(detail::eat_chars(
                        &(first_char[2]),
                        &isspace
                    ));
{'fraction_non_alphanumeric': 0.10695842450765865, 'fraction_numerical': 0.009452954048140044, 'mean_word_length': 1.4064869418702612, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '499928', 'n_tokens_mistral': 3342, 'n_tokens_neox': 3151, 'n_words': 712}