text:
/*
 *
 * Copyright (c) 2004
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         regex_traits_defaults.hpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: Declares API's for access to regex_traits default properties.
  */

#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
#define BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_PREFIX
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

#include <boost/regex/config.hpp>
#include <boost/cstdint.hpp>

#include <cctype>
#include <cwctype>
#include <locale>

#ifndef BOOST_REGEX_SYNTAX_TYPE_HPP
#include <boost/regex/v4/syntax_type.hpp>
#endif
#ifndef BOOST_REGEX_ERROR_TYPE_HPP
#include <boost/regex/v4/error_type.hpp>
#endif
#include <boost/regex/v4/regex_workaround.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/utility/enable_if.hpp>

#ifdef BOOST_NO_STDC_NAMESPACE
namespace std{
   using ::strlen;
}
#endif

namespace boost{ namespace BOOST_REGEX_DETAIL_NS{

//
// helpers to suppress warnings:
//
template <class charT>
inline bool is_extended(charT c)
{
   typedef typename make_unsigned<charT>::type unsigned_type;
   return (sizeof(charT) > 1) && (static_cast<unsigned_type>(c) >= 256u);
}
inline bool is_extended(char)
{ return false; }

inline const char* BOOST_REGEX_CALL get_default_syntax(regex_constants::syntax_type n)
{
   // if the user hasn't supplied a message catalog, then this supplies
   // default "messages" for us to load in the range 1-100.
   const char* messages[] = {
         "",
         "(",
         ")",
         "$",
         "^",
         ".",
         "*",
         "+",
         "?",
         "[",
         "]",
         "|",
         "\\",
         "#",
         "-",
         "{",
         "}",
         "0123456789",
         "b",
         "B",
         "<",
         ">",
         "",
         "",
         "A`",
         "z'",
         "\n",
         ",",
         "a",
         "f",
         "n",
         "r",
         "t",
         "v",
         "x",
         "c",
         ":",
         "=",
         "e",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "E",
         "Q",
         "X",
         "C",
         "Z",
         "G",
         "!",
         "p",
         "P",
         "N",
         "gk",
         "K",
         "R",
   };

   return ((n >= (sizeof(messages) / sizeof(messages[1]))) ? "" : messages[n]);
}

inline const char* BOOST_REGEX_CALL get_default_error_string(regex_constants::error_type n)
{
   static const char* const s_default_error_messages[] = {
      "Success",                                                            /* REG_NOERROR 0 error_ok */
      "No match",                                                           /* REG_NOMATCH 1 error_no_match */
      "Invalid regular expression.",                                        /* REG_BADPAT 2 error_bad_pattern */
      "Invalid collation character.",                                       /* REG_ECOLLATE 3 error_collate */
      "Invalid character class name, collating name, or character range.",  /* REG_ECTYPE 4 error_ctype */
      "Invalid or unterminated escape sequence.",                           /* REG_EESCAPE 5 error_escape */
      "Invalid back reference: specified capturing group does not exist.",  /* REG_ESUBREG 6 error_backref */
      "Unmatched [ or [^ in character class declaration.",                  /* REG_EBRACK 7 error_brack */
      "Unmatched marking parenthesis ( or \\(.",                            /* REG_EPAREN 8 error_paren */
      "Unmatched quantified repeat operator { or \\{.",                     /* REG_EBRACE 9 error_brace */
      "Invalid content of repeat range.",                                   /* REG_BADBR 10 error_badbrace */
      "Invalid range end in character class",                               /* REG_ERANGE 11 error_range */
      "Out of memory.",                                                     /* REG_ESPACE 12 error_space NOT USED */
      "Invalid preceding regular expression prior to repetition operator.", /* REG_BADRPT 13 error_badrepeat */
      "Premature end of regular expression",                                /* REG_EEND 14 error_end NOT USED */
      "Regular expression is too large.",                                   /* REG_ESIZE 15 error_size NOT USED */
      "Unmatched ) or \\)",                                                 /* REG_ERPAREN 16 error_right_paren NOT USED */
      "Empty regular expression.",                                          /* REG_EMPTY 17 error_empty */
      "The complexity of matching the regular expression exceeded predefined bounds.  "
      "Try refactoring the regular expression to make each choice made by the state machine unambiguous.  "
      "This exception is thrown to prevent \"eternal\" matches that take an "
      "indefinite period time to locate.",                                  /* REG_ECOMPLEXITY 18 error_complexity */
      "Ran out of stack space trying to match the regular expression.",     /* REG_ESTACK 19 error_stack */
      "Invalid or unterminated Perl (?...) sequence.",                      /* REG_E_PERL 20 error_perl */
      "Unknown error.",                                                     /* REG_E_UNKNOWN 21 error_unknown */
   };

   return (n > ::boost::regex_constants::error_unknown) ? s_default_error_messages[::boost::regex_constants::error_unknown] : s_default_error_messages[n];
}

inline regex_constants::syntax_type BOOST_REGEX_CALL get_default_syntax_type(char c)
{
   //
   // char_syntax determines how the compiler treats a given character
   // in a regular expression.
   //
   static regex_constants::syntax_type char_syntax[] = {
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_newline,     /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /* */    // 32
      regex_constants::syntax_not,        /*!*/
      regex_constants::syntax_char,        /*"*/
      regex_constants::syntax_hash,        /*#*/
      regex_constants::syntax_dollar,        /*$*/
      regex_constants::syntax_char,        /*%*/
      regex_constants::syntax_char,        /*&*/
      regex_constants::escape_type_end_buffer,  /*'*/
      regex_constants::syntax_open_mark,        /*(*/
      regex_constants::syntax_close_mark,        /*)*/
      regex_constants::syntax_star,        /***/
      regex_constants::syntax_plus,        /*+*/
      regex_constants::syntax_comma,        /*,*/
      regex_constants::syntax_dash,        /*-*/
      regex_constants::syntax_dot,        /*.*/
      regex_constants::syntax_char,        /*/*/
      regex_constants::syntax_digit,        /*0*/
      regex_constants::syntax_digit,        /*1*/
      regex_constants::syntax_digit,        /*2*/
      regex_constants::syntax_digit,        /*3*/
      regex_constants::syntax_digit,        /*4*/
      regex_constants::syntax_digit,        /*5*/
      regex_constants::syntax_digit,        /*6*/
      regex_constants::syntax_digit,        /*7*/
      regex_constants::syntax_digit,        /*8*/
      regex_constants::syntax_digit,        /*9*/
      regex_constants::syntax_colon,        /*:*/
      regex_constants::syntax_char,        /*;*/
      regex_constants::escape_type_left_word, /*<*/
      regex_constants::syntax_equal,        /*=*/
      regex_constants::escape_type_right_word, /*>*/
      regex_constants::syntax_question,        /*?*/
      regex_constants::syntax_char,        /*@*/
      regex_constants::syntax_char,        /*A*/
      regex_constants::syntax_char,        /*B*/
      regex_constants::syntax_char,        /*C*/
      regex_constants::syntax_char,        /*D*/
      regex_constants::syntax_char,        /*E*/
      regex_constants::syntax_char,        /*F*/
      regex_constants::syntax_char,        /*G*/
      regex_constants::syntax_char,        /*H*/
      regex_constants::syntax_char,        /*I*/
      regex_constants::syntax_char,        /*J*/
      regex_constants::syntax_char,        /*K*/
      regex_constants::syntax_char,        /*L*/
      regex_constants::syntax_char,        /*M*/
      regex_constants::syntax_char,        /*N*/
      regex_constants::syntax_char,        /*O*/
      regex_constants::syntax_char,        /*P*/
      regex_constants::syntax_char,        /*Q*/
      regex_constants::syntax_char,        /*R*/
      regex_constants::syntax_char,        /*S*/
      regex_constants::syntax_char,        /*T*/
      regex_constants::syntax_char,        /*U*/
      regex_constants::syntax_char,        /*V*/
      regex_constants::syntax_char,        /*W*/
      regex_constants::syntax_char,        /*X*/
      regex_constants::syntax_char,        /*Y*/
      regex_constants::syntax_char,        /*Z*/
      regex_constants::syntax_open_set,        /*[*/
      regex_constants::syntax_escape,        /*\*/
      regex_constants::syntax_close_set,        /*]*/
      regex_constants::syntax_caret,        /*^*/
      regex_constants::syntax_char,        /*_*/
      regex_constants::syntax_char,        /*`*/
      regex_constants::syntax_char,        /*a*/
      regex_constants::syntax_char,        /*b*/
      regex_constants::syntax_char,        /*c*/
      regex_constants::syntax_char,        /*d*/
      regex_constants::syntax_char,        /*e*/
      regex_constants::syntax_char,        /*f*/
      regex_constants::syntax_char,        /*g*/
      regex_constants::syntax_char,        /*h*/
      regex_constants::syntax_char,        /*i*/
      regex_constants::syntax_char,        /*j*/
      regex_constants::syntax_char,        /*k*/
      regex_constants::syntax_char,        /*l*/
      regex_constants::syntax_char,        /*m*/
      regex_constants::syntax_char,        /*n*/
      regex_constants::syntax_char,        /*o*/
      regex_constants::syntax_char,        /*p*/
      regex_constants::syntax_char,        /*q*/
      regex_constants::syntax_char,        /*r*/
      regex_constants::syntax_char,        /*s*/
      regex_constants::syntax_char,        /*t*/
      regex_constants::syntax_char,        /*u*/
      regex_constants::syntax_char,        /*v*/
      regex_constants::syntax_char,        /*w*/
      regex_constants::syntax_char,        /*x*/
      regex_constants::syntax_char,        /*y*/
      regex_constants::syntax_char,        /*z*/
      regex_constants::syntax_open_brace,        /*{*/
      regex_constants::syntax_or,        /*|*/
      regex_constants::syntax_close_brace,        /*}*/
      regex_constants::syntax_char,        /*~*/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
      regex_constants::syntax_char,        /**/
   };

   return char_syntax[(unsigned char)c];
}

inline regex_constants::escape_syntax_type BOOST_REGEX_CALL get_default_escape_syntax_type(char c)
{
   //
   // char_syntax determines how the compiler treats a given character
   // in a regular expression.
   //
   static regex_constants::escape_syntax_type char_syntax[] = {
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,     /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /* */    // 32
      regex_constants::escape_type_identity,        /*!*/
      regex_constants::escape_type_identity,        /*"*/
      regex_constants::escape_type_identity,        /*#*/
      regex_constants::escape_type_identity,        /*$*/
      regex_constants::escape_type_identity,        /*%*/
      regex_constants::escape_type_identity,        /*&*/
      regex_constants::escape_type_end_buffer,        /*'*/
      regex_constants::syntax_open_mark,        /*(*/
      regex_constants::syntax_close_mark,        /*)*/
      regex_constants::escape_type_identity,        /***/
      regex_constants::syntax_plus,                 /*+*/
      regex_constants::escape_type_identity,        /*,*/
      regex_constants::escape_type_identity,        /*-*/
      regex_constants::escape_type_identity,        /*.*/
      regex_constants::escape_type_identity,        /*/*/
      regex_constants::escape_type_decimal,        /*0*/
      regex_constants::escape_type_backref,        /*1*/
      regex_constants::escape_type_backref,        /*2*/
      regex_constants::escape_type_backref,        /*3*/
      regex_constants::escape_type_backref,        /*4*/
      regex_constants::escape_type_backref,        /*5*/
      regex_constants::escape_type_backref,        /*6*/
      regex_constants::escape_type_backref,        /*7*/
      regex_constants::escape_type_backref,        /*8*/
      regex_constants::escape_type_backref,        /*9*/
      regex_constants::escape_type_identity,        /*:*/
      regex_constants::escape_type_identity,        /*;*/
      regex_constants::escape_type_left_word,        /*<*/
      regex_constants::escape_type_identity,        /*=*/
      regex_constants::escape_type_right_word,        /*>*/
      regex_constants::syntax_question,              /*?*/
      regex_constants::escape_type_identity,         /*@*/
      regex_constants::escape_type_start_buffer,     /*A*/
      regex_constants::escape_type_not_word_assert,  /*B*/
      regex_constants::escape_type_C,                /*C*/
      regex_constants::escape_type_not_class,        /*D*/
      regex_constants::escape_type_E,                /*E*/
      regex_constants::escape_type_not_class,        /*F*/
      regex_constants::escape_type_G,                /*G*/
      regex_constants::escape_type_not_class,        /*H*/
      regex_constants::escape_type_not_class,        /*I*/
      regex_constants::escape_type_not_class,        /*J*/
      regex_constants::escape_type_reset_start_mark, /*K*/
      regex_constants::escape_type_not_class,        /*L*/
      regex_constants::escape_type_not_class,        /*M*/
      regex_constants::escape_type_named_char,       /*N*/
      regex_constants::escape_type_not_class,        /*O*/
      regex_constants::escape_type_not_property,     /*P*/
      regex_constants::escape_type_Q,                /*Q*/
      regex_constants::escape_type_line_ending,      /*R*/
      regex_constants::escape_type_not_class,        /*S*/
      regex_constants::escape_type_not_class,        /*T*/
      regex_constants::escape_type_not_class,        /*U*/
      regex_constants::escape_type_not_class,        /*V*/
      regex_constants::escape_type_not_class,        /*W*/
      regex_constants::escape_type_X,                /*X*/
      regex_constants::escape_type_not_class,        /*Y*/
      regex_constants::escape_type_Z,                /*Z*/
      regex_constants::escape_type_identity,        /*[*/
      regex_constants::escape_type_identity,        /*\*/
      regex_constants::escape_type_identity,        /*]*/
      regex_constants::escape_type_identity,        /*^*/
      regex_constants::escape_type_identity,        /*_*/
      regex_constants::escape_type_start_buffer,        /*`*/
      regex_constants::escape_type_control_a,        /*a*/
      regex_constants::escape_type_word_assert,        /*b*/
      regex_constants::escape_type_ascii_control,        /*c*/
      regex_constants::escape_type_class,        /*d*/
      regex_constants::escape_type_e,        /*e*/
      regex_constants::escape_type_control_f,       /*f*/
      regex_constants::escape_type_extended_backref,  /*g*/
      regex_constants::escape_type_class,        /*h*/
      regex_constants::escape_type_class,        /*i*/
      regex_constants::escape_type_class,        /*j*/
      regex_constants::escape_type_extended_backref, /*k*/
      regex_constants::escape_type_class,        /*l*/
      regex_constants::escape_type_class,        /*m*/
      regex_constants::escape_type_control_n,       /*n*/
      regex_constants::escape_type_class,           /*o*/
      regex_constants::escape_type_property,        /*p*/
      regex_constants::escape_type_class,           /*q*/
      regex_constants::escape_type_control_r,       /*r*/
      regex_constants::escape_type_class,           /*s*/
      regex_constants::escape_type_control_t,       /*t*/
      regex_constants::escape_type_class,         /*u*/
      regex_constants::escape_type_control_v,       /*v*/
      regex_constants::escape_type_class,           /*w*/
      regex_constants::escape_type_hex,             /*x*/
      regex_constants::escape_type_class,           /*y*/
      regex_constants::escape_type_end_buffer,      /*z*/
      regex_constants::syntax_open_brace,           /*{*/
      regex_constants::syntax_or,                   /*|*/
      regex_constants::syntax_close_brace,          /*}*/
      regex_constants::escape_type_identity,        /*~*/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
      regex_constants::escape_type_identity,        /**/
   };

   return char_syntax[(unsigned char)c];
}

// is charT c a combining character?
inline bool BOOST_REGEX_CALL is_combining_implementation(boost::uint_least16_t c)
{
   const boost::uint_least16_t combining_ranges[] = { 0x0300, 0x0361,
                           0x0483, 0x0486,
                           0x0903, 0x0903,
                           0x093E, 0x0940,
                           0x0949, 0x094C,
                           0x0982, 0x0983,
                           0x09BE, 0x09C0,
                           0x09C7, 0x09CC,
                           0x09D7, 0x09D7,
                           0x0A3E, 0x0A40,
                           0x0A83, 0x0A83,
                           0x0ABE, 0x0AC0,
                           0x0AC9, 0x0ACC,
                           0x0B02, 0x0B03,
                           0x0B3E, 0x0B3E,
                           0x0B40, 0x0B40,
                           0x0B47, 0x0B4C,
                           0x0B57, 0x0B57,
                           0x0B83, 0x0B83,
                           0x0BBE, 0x0BBF,
                           0x0BC1, 0x0BCC,
                           0x0BD7, 0x0BD7,
                           0x0C01, 0x0C03,
                           0x0C41, 0x0C44,
                           0x0C82, 0x0C83,
                           0x0CBE, 0x0CBE,
                           0x0CC0, 0x0CC4,
                           0x0CC7, 0x0CCB,
                           0x0CD5, 0x0CD6,
                           0x0D02, 0x0D03,
                           0x0D3E, 0x0D40,
                           0x0D46, 0x0D4C,
                           0x0D57, 0x0D57,
                           0x0F7F, 0x0F7F,
                           0x20D0, 0x20E1,
                           0x3099, 0x309A,
                           0xFE20, 0xFE23,
                           0xffff, 0xffff, };

   const boost::uint_least16_t* p = combining_ranges + 1;
   while (*p < c) p += 2;
   --p;
   if ((c >= *p) && (c <= *(p + 1)))
      return true;
   return false;
}

template <class charT>
inline bool is_combining(charT c)
{
   return (c <= static_cast<charT>(0)) ? false : ((c >= static_cast<charT>((std::numeric_limits<uint_least16_t>::max)())) ? false : is_combining_implementation(static_cast<unsigned short>(c)));
}
template <>
inline bool is_combining<char>(char)
{
   return false;
}
template <>
inline bool is_combining<signed char>(signed char)
{
   return false;
}
template <>
inline bool is_combining<unsigned char>(unsigned char)
{
   return false;
}
#if !defined(__hpux) && !defined(__WINSCW__) // can't use WCHAR_MAX/MIN in pp-directives
#ifdef _MSC_VER
template<>
inline bool is_combining<wchar_t>(wchar_t c)
{
   return is_combining_implementation(static_cast<unsigned short>(c));
}
#elif !defined(__DECCXX) && !defined(__osf__) && !defined(__OSF__) && defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
#if defined(WCHAR_MAX) && (WCHAR_MAX <= USHRT_MAX)
template<>
inline bool is_combining<wchar_t>(wchar_t c)
{
   return is_combining_implementation(static_cast<unsigned short>(c));
}
#else
template<>
inline bool is_combining<wchar_t>(wchar_t c)
{
   return (c >= (std::numeric_limits<uint_least16_t>::max)()) ? false : is_combining_implementation(static_cast<unsigned short>(c));
}
#endif
#endif
#endif

//
// is a charT c a line separator?
//
template <class charT>
inline bool is_separator(charT c)
{
   return BOOST_REGEX_MAKE_BOOL(
      (c == static_cast<charT>('\n'))
      || (c == static_cast<charT>('\r'))
      || (c == static_cast<charT>('\f'))
      || (static_cast<boost::uint16_t>(c) == 0x2028u)
      || (static_cast<boost::uint16_t>(c) == 0x2029u)
      || (static_cast<boost::uint16_t>(c) == 0x85u));
}
template <>
inline bool is_separator<char>(char c)
{
   return BOOST_REGEX_MAKE_BOOL((c == '\n') || (c == '\r') || (c == '\f'));
}

//
// get a default collating element:
//
inline std::string BOOST_REGEX_CALL lookup_default_collate_name(const std::string& name)
{
   //
   // these are the POSIX collating names:
   //
   static const char* def_coll_names[] = {
   "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "alert", "backspace", "tab", "newline",
   "vertical-tab", "form-feed", "carriage-return", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK",
   "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "IS4", "IS3", "IS2", "IS1", "space", "exclamation-mark",
   "quotation-mark", "number-sign", "dollar-sign", "percent-sign", "ampersand", "apostrophe",
   "left-parenthesis", "right-parenthesis", "asterisk", "plus-sign", "comma", "hyphen",
   "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
   "colon", "semicolon", "less-than-sign", "equals-sign", "greater-than-sign",
   "question-mark", "commercial-at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P",
   "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "left-square-bracket", "backslash",
   "right-square-bracket", "circumflex", "underscore", "grave-accent", "a", "b", "c", "d", "e", "f",
   "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "left-curly-bracket",
   "vertical-line", "right-curly-bracket", "tilde", "DEL", "",
   };

   // these multi-character collating elements
   // should keep most Western-European locales
   // happy - we should really localise these a
   // little more - but this will have to do for
   // now:

   static const char* def_multi_coll[] = {
      "ae",
      "Ae",
      "AE",
      "ch",
      "Ch",
      "CH",
      "ll",
      "Ll",
      "LL",
      "ss",
      "Ss",
      "SS",
      "nj",
      "Nj",
      "NJ",
      "dz",
      "Dz",
      "DZ",
      "lj",
      "Lj",
      "LJ",
      "",
   };

   unsigned int i = 0;
   while (*def_coll_names[i])
   {
      if (def_coll_names[i] == name)
      {
         return std::string(1, char(i));
      }
      ++i;
   }
   i = 0;
   while (*def_multi_coll[i])
   {
      if (def_multi_coll[i] == name)
      {
         return def_multi_coll[i];
      }
      ++i;
   }
   return std::string();
}

//
// get the state_id of a character classification, the individual
// traits classes then transform that state_id into a bitmask:
//
template <class charT>
struct character_pointer_range
{
   const charT* p1;
   const charT* p2;

   bool operator < (const character_pointer_range& r)const
   {
      return std::lexicographical_compare(p1, p2, r.p1, r.p2);
   }
   bool operator == (const character_pointer_range& r)const
   {
      // Not only do we check that the ranges are of equal size before
      // calling std::equal, but there is no other algorithm available:
      // not even a non-standard MS one.  So forward to unchecked_equal
      // in the MS case.
      return ((p2 - p1) == (r.p2 - r.p1)) && BOOST_REGEX_DETAIL_NS::equal(p1, p2, r.p1);
   }
};
template <class charT>
int get_default_class_id(const charT* p1, const charT* p2)
{
   static const charT data[73] = {
      'a', 'l', 'n', 'u', 'm',
      'a', 'l', 'p', 'h', 'a',
      'b', 'l', 'a', 'n', 'k',
      'c', 'n', 't', 'r', 'l',
      'd', 'i', 'g', 'i', 't',
      'g', 'r', 'a', 'p', 'h',
      'l', 'o', 'w', 'e', 'r',
      'p', 'r', 'i', 'n', 't',
      'p', 'u', 'n', 'c', 't',
      's', 'p', 'a', 'c', 'e',
      'u', 'n', 'i', 'c', 'o', 'd', 'e',
      'u', 'p', 'p', 'e', 'r',
      'v',
      'w', 'o', 'r', 'd',
      'x', 'd', 'i', 'g', 'i', 't',
   };

   static const character_pointer_range<charT> ranges[21] =
   {
      {data+0, data+5,}, // alnum
      {data+5, data+10,}, // alpha
      {data+10, data+15,}, // blank
      {data+15, data+20,}, // cntrl
      {data+20, data+21,}, // d
      {data+20, data+25,}, // digit
      {data+25, data+30,}, // graph
      {data+29, data+30,}, // h
      {data+30, data+31,}, // l
      {data+30, data+35,}, // lower
      {data+35, data+40,}, // print
      {data+40, data+45,}, // punct
      {data+45, data+46,}, // s
      {data+45, data+50,}, // space
      {data+57, data+58,}, // u
      {data+50, data+57,}, // unicode
      {data+57, data+62,}, // upper
      {data+62, data+63,}, // v
      {data+63, data+64,}, // w
      {data+63, data+67,}, // word
      {data+67, data+73,}, // xdigit
   };
   const character_pointer_range<charT>* ranges_begin = ranges;
   const character_pointer_range<charT>* ranges_end = ranges + (sizeof(ranges)/sizeof(ranges[0]));

   character_pointer_range<charT> t = { p1, p2, };
   const character_pointer_range<charT>* p = std::lower_bound(ranges_begin, ranges_end, t);
   if((p != ranges_end) && (t == *p))
      return static_cast<int>(p - ranges);
   return -1;
}

//
// helper functions:
//
template <class charT>
std::ptrdiff_t global_length(const charT* p)
{
   std::ptrdiff_t n = 0;
   while(*p)
   {
      ++p;
      ++n;
   }
   return n;
}
template<>
inline std::ptrdiff_t global_length<char>(const char* p)
{
   return (std::strlen)(p);
}
#ifndef BOOST_NO_WREGEX
template<>
inline std::ptrdiff_t global_length<wchar_t>(const wchar_t* p)
{
   return (std::ptrdiff_t)(std::wcslen)(p);
}
#endif
template <class charT>
inline charT BOOST_REGEX_CALL global_lower(charT c)
{
   return c;
}
template <class charT>
inline charT BOOST_REGEX_CALL global_upper(charT c)
{
   return c;
}

inline char BOOST_REGEX_CALL do_global_lower(char c)
{
   return static_cast<char>((std::tolower)((unsigned char)c));
}

inline char BOOST_REGEX_CALL do_global_upper(char c)
{
   return static_cast<char>((std::toupper)((unsigned char)c));
}
#ifndef BOOST_NO_WREGEX
inline wchar_t BOOST_REGEX_CALL do_global_lower(wchar_t c)
{
   return (std::towlower)(c);
}

inline wchar_t BOOST_REGEX_CALL do_global_upper(wchar_t c)
{
   return (std::towupper)(c);
}
#endif
//
// This sucks: declare template specialisations of global_lower/global_upper
// that just forward to the non-template implementation functions.  We do
// this because there is one compiler (Compaq Tru64 C++) that doesn't seem
// to differentiate between templates and non-template overloads....
// what's more, the primary template, plus all overloads have to be
// defined in the same translation unit (if one is inline they all must be)
// otherwise the "local template instantiation" compiler option can pick
// the wrong instantiation when linking:
//
template<> inline char BOOST_REGEX_CALL global_lower<char>(char c) { return do_global_lower(c); }
template<> inline char BOOST_REGEX_CALL global_upper<char>(char c) { return do_global_upper(c); }
#ifndef BOOST_NO_WREGEX
template<> inline wchar_t BOOST_REGEX_CALL global_lower<wchar_t>(wchar_t c) { return do_global_lower(c); }
template<> inline wchar_t BOOST_REGEX_CALL global_upper<wchar_t>(wchar_t c) { return do_global_upper(c); }
#endif

template <class charT>
int global_value(charT c)
{
   static const charT zero = '0';
   static const charT nine = '9';
   static const charT a = 'a';
   static const charT f = 'f';
   static const charT A = 'A';
   static const charT F = 'F';

   if(c > f) return -1;
   if(c >= a) return 10 + (c - a);
   if(c > F) return -1;
   if(c >= A) return 10 + (c - A);
   if(c > nine) return -1;
   if(c >= zero) return c - zero;
   return -1;
}
template <class charT, class traits>
boost::intmax_t global_toi(const charT*& p1, const charT* p2, int radix, const traits& t)
{
   (void)t; // warning suppression
   boost::intmax_t limit = (std::numeric_limits<boost::intmax_t>::max)() / radix;
   boost::intmax_t next_value = t.value(*p1, radix);
   if((p1 == p2) || (next_value < 0) || (next_value >= radix))
      return -1;
   boost::intmax_t result = 0;
   while(p1 != p2)
   {
      next_value = t.value(*p1, radix);
      if((next_value < 0) || (next_value >= radix))
         break;
      result *= radix;
      result += next_value;
      ++p1;
      if (result > limit)
         return -1;
   }
   return result;
}

template <class charT>
inline typename boost::enable_if_c<(sizeof(charT) > 1), const charT*>::type get_escape_R_string()
{
#ifdef BOOST_MSVC
#  pragma warning(push)
#  pragma warning(disable:4309 4245)
#endif
   static const charT e1[] = { '(', '?', '-', 'x', ':', '(', '?', '>', '\x0D', '\x0A', '?',
      '|', '[', '\x0A', '\x0B', '\x0C', static_cast<charT>(0x85), static_cast<charT>(0x2028),
      static_cast<charT>(0x2029), ']', ')', ')', '\0' };
   static const charT e2[] = { '(', '?', '-', 'x', ':', '(', '?', '>', '\x0D', '\x0A', '?',
      '|', '[', '\x0A', '\x0B', '\x0C', static_cast<charT>(0x85), ']', ')', ')', '\0' };

   charT c = static_cast<charT>(0x2029u);
   bool b = (static_cast<unsigned>(c) == 0x2029u);

   return (b ? e1 : e2);
#ifdef BOOST_MSVC
#  pragma warning(pop)
#endif
}

template <class charT>
inline typename boost::disable_if_c<(sizeof(charT) > 1), const charT*>::type get_escape_R_string()
{
#ifdef BOOST_MSVC
#  pragma warning(push)
#  pragma warning(disable:4309)
#endif
   static const charT e2[] = { '(', '?', '-', 'x', ':', '(', '?', '>', '\x0D', '\x0A', '?',
      '|', '[', '\x0A', '\x0B', '\x0C', '\x85', ']', ')', ')', '\0' };
   return e2;
#ifdef BOOST_MSVC
#  pragma warning(pop)
#endif
}

} // BOOST_REGEX_DETAIL_NS
} // boost

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_SUFFIX
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

#endif


text:
/**
 * \author Norihiro Watanabe
 * \date   2013-04-16
 *
 * \copyright
 * Copyright (c) 2013, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 *
 */

#include <iostream>

#include <boost/range/algorithm/for_each.hpp>

#include "MeshLib/MeshSubsets.h"

#include "MeshComponentMap.h"

namespace AssemblerLib
{

using namespace detail;

std::size_t const MeshComponentMap::nop = std::numeric_limits<std::size_t>::max();

MeshComponentMap::MeshComponentMap(
    const std::vector<MeshLib::MeshSubsets*> &components, ComponentOrder order)
{
    // construct dict (and here we number global_index by component type)
    std::size_t global_index = 0;
    std::size_t comp_id = 0;
    for (auto c = components.cbegin(); c != components.cend(); ++c)
    {
        for (unsigned mesh_subset_index = 0; mesh_subset_index < (*c)->size(); mesh_subset_index++)
        {
            MeshLib::MeshSubset const& mesh_subset = (*c)->getMeshSubset(mesh_subset_index);
            std::size_t const mesh_id = mesh_subset.getMeshID();
            // mesh items are ordered first by node, cell, ....
            for (std::size_t j=0; j<mesh_subset.getNNodes(); j++)
                _dict.insert(Line(Location(mesh_id, MeshLib::MeshItemType::Node, j), comp_id, global_index++));
            for (std::size_t j=0; j<mesh_subset.getNElements(); j++)
                _dict.insert(Line(Location(mesh_id, MeshLib::MeshItemType::Cell, j), comp_id, global_index++));
        }
        comp_id++;
    }

    if (order == ComponentOrder::BY_LOCATION)
        renumberByLocation();
}

void MeshComponentMap::renumberByLocation(std::size_t offset)
{
    std::size_t global_index = offset;

    auto &m = _dict.get<ByLocation>(); // view as sorted by mesh item
    for (auto itr_mesh_item=m.begin(); itr_mesh_item!=m.end(); ++itr_mesh_item)
    {
        Line pos = *itr_mesh_item;
        pos.global_index = global_index++;
        m.replace(itr_mesh_item, pos);
    }
}

std::vector<std::size_t> MeshComponentMap::getComponentIDs(const Location &l) const
{
    auto const &m = _dict.get<ByLocation>();
    auto const p = m.equal_range(Line(l));
    std::vector<std::size_t> vec_compID;
    for (auto itr=p.first; itr!=p.second; ++itr)
        vec_compID.push_back(itr->comp_id);
    return vec_compID;
}

std::size_t MeshComponentMap::getGlobalIndex(Location const& l,
    std::size_t const c) const
{
    auto const &m = _dict.get<ByLocationAndComponent>();
    auto const itr = m.find(Line(l, c));
    return itr!=m.end() ? itr->global_index : nop;
}

std::vector<std::size_t> MeshComponentMap::getGlobalIndices(const Location &l) const
{
    auto const &m = _dict.get<ByLocation>();
    auto const p = m.equal_range(Line(l));
    std::vector<std::size_t> global_indices;
    for (auto itr=p.first; itr!=p.second; ++itr)
        global_indices.push_back(itr->global_index);
    return global_indices;
}

template <>
std::vector<std::size_t>
MeshComponentMap::getGlobalIndices<ComponentOrder::BY_LOCATION>(
    std::vector<Location> const &ls) const
{
    // Create vector of global indices sorted by location containing all
    // locations given in ls parameter.

    std::vector<std::size_t> global_indices;
    global_indices.reserve(ls.size());

    auto const &m = _dict.get<ByLocation>();
    for (auto l = ls.cbegin(); l != ls.cend(); ++l)
    {
        auto const p = m.equal_range(Line(*l));
        for (auto itr = p.first; itr != p.second; ++itr)
            global_indices.push_back(itr->global_index);
    }

    return global_indices;
}

template <>
std::vector<std::size_t>
MeshComponentMap::getGlobalIndices<ComponentOrder::BY_COMPONENT>(
    std::vector<Location> const &ls) const
{
    // vector of (Component, global Index) pairs.
    typedef std::pair<std::size_t, std::size_t> CIPair;
    std::vector<CIPair> pairs;
    pairs.reserve(ls.size());

    // Create a sub dictionary containing all lines with location from ls.
    auto const &m = _dict.get<ByLocation>();
    for (auto l = ls.cbegin(); l != ls.cend(); ++l)
    {
        auto const p = m.equal_range(Line(*l));
        for (auto itr = p.first; itr != p.second; ++itr)
            pairs.emplace_back(itr->comp_id, itr->global_index);
    }

    auto CIPairLess = [](CIPair const& a, CIPair const& b)
        {
            return a.first < b.first;
        };

    // Create vector of global indices from sub dictionary sorting by component.
    if (!std::is_sorted(pairs.begin(), pairs.end(), CIPairLess))
        std::stable_sort(pairs.begin(), pairs.end(), CIPairLess);

    std::vector<std::size_t> global_indices;
    global_indices.reserve(pairs.size());
    for (auto p = pairs.cbegin(); p != pairs.cend(); ++p)
        global_indices.push_back(p->second);

    return global_indices;
}

}   // namespace AssemblerLib

ext: cpp

max_stars_repo_name: WenjieXu/ogs

max_issues_repo_name: WenjieXu/ogs

max_forks_repo_name: WenjieXu/ogs


text:
//
// $Id$
//
// -------------------------------------------------------------------------
// This file is part of ZeroBugs, Copyright (c) 2010 Cristian L. Vlasceanu
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// -------------------------------------------------------------------------
//
#include <assert.h>
#include <stdexcept>
#include <string>
#include <boost/tokenizer.hpp>
#include "generic/temporary.h"
#include "zdk/check_ptr.h"
#include "zdk/container.h"
#include "zdk/types.h"
#include "zdk/variant_util.h"
#include "typez/public/debug_symbol_impl.h"
#include "typez/public/lookup_child.h"
#include "call_setup.h"
#include "cast_expr.h"
#include "collect_symbol.h"
#include "debug_out.h"
#include "errors.h"
#include "eval_inc_dec.h"
#include "ident.h"
#include "interp.h"
#include "lookup_methods.h"
#include "postfix_expr.h"
#include "rtti_disabler.h"
#include "slicer.h"
#include "type_spec.h"
#include "unary_expr.h"
#include "variant_assign.h"
#include "variant_impl.h"

using namespace std;

/**
 * Helper used for evaluating the '.' and '->' operators
 */
static ClassType&
get_class_type(DataType* type, const string& member)
{
    ClassType* klass = interface_cast<ClassType*>(type);
    if (!klass)
    {
        string err("requesting '" + member + "' in non-aggregate ");
        err += CHKPTR(type->name())->c_str();

        throw EvalError(err);
    }
    return *klass;
}

PostfixExpr::PostfixExpr
(
    Interp*             interp,
    Operator            oper,
    const RefPtr<Expr>& expr,
    const RefPtr<Expr>& param
)
  : Expr(interp)
  , oper_(oper)
  , expr_(expr)
  , param_(param)
  , isMacroCall_(false)
{
    assert(expr_.get());

    if (!param_)
    {
        assert(oper_ == FCALL || oper_ == INC || oper_ == DEC);
    }
    if (oper_ == MEMBER
     || oper_ == POINTER
     || oper_ == VPOINTER
     || oper_ == PTR_TO_MEMBER)
    {
        assert(param_);
        ident_ = &interface_cast<Ident&>(*param_);
    }
}

PostfixExpr::~PostfixExpr() throw()
{
}

RefPtr<Variant> PostfixExpr::eval_impl(Context& context)
{
    auto_ptr<RTTI_Disabler> rttiDisable;
    if (oper_ != VPOINTER)
    {
        // all but operator => disable auto-RTTI because we don't
        // want a pointer to the most-derived object to be returned;
        // operator => is my own extension to the language, useful
        // for testing
        rttiDisable.reset(new RTTI_Disabler(context.type_system()));
    }
    context.set_macro_helper(this);
    RefPtr<Variant> lval = expr_->eval(context);

    if (!lval)
    {
        throw logic_error("base expression yielded null");
    }
    if (isMacroCall_)
    {
        set_result(lval);
        assert(type() == expr_->type());
        return lval;
    }
    // type should be known at this point;
    // if not, then it's a programming mistake somewhere
    if (lval->type_tag() == Variant::VT_NONE || !expr_->type())
    {
        throw logic_error("unknown argument type");
    }
    RefPtr<Variant> result;

    if ((oper_ != POINTER) && (oper_ != VPOINTER))
    {
        // handle pointer operator separately
        RefPtr<CallSetup> op = get_overloaded_operator(context);
        if (op.get())
        {
            dump_args(context, op->args());
            initiate_fun_call(context, *op);
            return result;
        }
    }
    switch (oper_)
    {
    case ARRAY:
        result = eval_array(context, *lval);
        break;

    case ARANGE:
        result = eval_array_range(context, *lval);
        break;

    case FCALL:
        result = eval_function_call(context, *lval);
        break;

    case MEMBER:
        result = eval_member(context, *lval);
        break;

    case PTR_TO_MEMBER:
        result = eval_ptr_to_member(context, *lval);
        break;

    case POINTER:
    case VPOINTER:
        {
            RefPtr<DebugSymbol> obj = eval_pointer(context, *lval);
            if (obj.get())
            {
                return eval_member(context, *obj, ident_->name(), true);
            }
        }
        break;

    case INC:
    case DEC:
        // the resulting expression is of the same type as the arg
        set_type(expr_->type());
        eval_inc_dec(context, *expr_->type(), *lval, (oper_ == INC));

        // copy the old value, but the symbol part,
        // since the result is a non l-value
        result = new VariantImpl;
        result->copy(lval.get(), false);
        break;
    }
    return result;
}

RefPtr<Variant>
PostfixExpr::eval_member(Context&        context,
                         DebugSymbol&    object,
                         const string&   memberName,
                         bool            isPointerOrRef)
{
    DataType* type = object.type();
    if (!type)
    {
        throw logic_error("null object type");
    }

    // is the base expression (left of the dot) a reference?
    if (PointerType* ref = interface_cast<PointerType*>(type))
    {
        if (isPointerOrRef || ref->is_reference())
        {
            // pointer to reference is illegal in C++
            assert(isPointerOrRef || oper_ != POINTER);
            type = ref->pointed_type();
        }
        isPointerOrRef = true;
    }
    if (DebugSymbol* parent = object.parent())
    {
        if (PointerType* ref = interface_cast<PointerType*>(parent->type()))
        {
            if (ref->is_reference())
            {
                isPointerOrRef = true;
            }
        }
    }

    RefPtr<DebugSymbol> sym = lookup_child(object, memberName.c_str());
    if (!sym)
    {
        // lookup methods polymorphically if pointer or reference
        const addr_t addr = isPointerOrRef ? object.addr() : 0;
        DEBUG_OUT << (void*)addr << endl;

        ClassType& klass = get_class_type(object.type(), memberName);
        sym = lookup_methods(context, klass, ident_->name(), addr);
    }
    if (!sym)
    {
        string err = CHKPTR(type->name())->c_str();
        err += " has no member named '" + memberName + "'";
        throw EvalError(err);
    }
    assert(sym->type());
    set_type(sym->type());

    // test for an overloaded function -- lookup_method may return
    // a FunType symbol that has the overloads as its children, and
    // a zero address; we don't want to read it, since the implementation
    // of DebugSymbol::read() resets the children.
    if (sym->addr() || sym->enum_children() == 0)
    {
        sym->read(&context);
    }
    assert(sym->addr() || sym->is_constant() || sym->enum_children());
    return new VariantImpl(*sym);
}

RefPtr<Variant> PostfixExpr::eval_member(Context& ctxt, const Variant& lval)
{
    RefPtr<DebugSymbol> obj = lval.debug_symbol();
    if (!obj)
    {
        throw EvalError("operator '.' with NULL object");
    }
    assert(ident_);
    return eval_member(ctxt, *obj, ident_->name());
}

RefPtr<Variant>
PostfixExpr::eval_ptr_to_member(Context& ctxt, const Variant& lval)
{
    RefPtr<DebugSymbol> obj = lval.debug_symbol();
    if (!obj)
    {
        throw EvalError("NULL base object");
    }
    if (!obj->type())
    {
        throw EvalError("NULL base type");
    }
    if (interface_cast<PointerType*>(obj->type()))
    {
        obj->read(&ctxt);
        obj = obj->nth_child(0);
        if (!obj)
        {
            throw EvalError("error dereferencing pointer");
        }
    }
    RefPtr<DebugSymbol> sym = ctxt.lookup_debug_symbol(CHKPTR(ident_)->name().c_str());
    if (!sym)
    {
        throw EvalError("symbol not found: " + ident_->name());
    }
    RefPtr<PtrToMemberType> ptrMem = interface_cast<PtrToMemberType*>(sym->type());
    if (!ptrMem)
    {
        throw EvalError(ident_->name() + " is not a pointer to member");
    }
    CHKPTR(ptrMem->pointed_type());

    if (!obj->type()->is_equal(CHKPTR(ptrMem->base_type())))
    {
        throw EvalError(string("pointer to member type ")
                        + CHKPTR(ptrMem->pointed_type()->name())->c_str()
                        + " incompatible with object type "
                        + CHKPTR(obj->type()->name())->c_str());
    }
    set_type(ptrMem->pointed_type());
    DebugSymbolImpl& impl = interface_cast<DebugSymbolImpl&>(*sym);
    impl.read(&ctxt);
    if (SharedString* val = impl.value())
    {
        impl.set_addr(strtoul(val->c_str(), 0, 0) + obj->addr());
        impl.set_type(*type());
        return new VariantImpl(impl);
    }
    return new VariantImpl;
}

/**
 * This is a separate function so that it can be used with both
 * "normal" pointers and overloaded -> operators; with the latter,
 * this function is called asynchronously after the operator call
 * returns.
 */
RefPtr<DebugSymbol> PostfixExpr::eval_pointer
(
    Context& ctxt,
    const RefPtr<Expr>& expr,
    const RefPtr<Variant>& var
)
{
    if (var->type_tag() != Variant::VT_POINTER)
    {
        throw EvalError("base operand of -> is not a pointer");
    }
    PointerType& ptrType = interface_cast<PointerType&>(*expr->type());
    if (ptrType.is_reference())
    {
        throw EvalError("base operand of -> is a reference");
    }
    RefPtr<DebugSymbol> symPtr = var->debug_symbol();
    if (!symPtr)
    {
        assert(ptrType.is_equal(expr_->type().get()));
        symPtr = ctxt.new_temp_ptr(ptrType, var->pointer());
    }

    if (!symPtr)
    {
        // this should only happen in the unit tests, because
        // the TestContext returns null temp pointers
        throw EvalError("base operand of -> is not a lvalue");
    }

    if (symPtr->addr() == 0 && !symPtr->value())
    {
        throw EvalError("dereferencing NULL pointer");
    }
    symPtr->read(&ctxt);

    // the pointer object is expected to have one child
    // (the debug symbol corresponding to the pointee)
    if (symPtr->enum_children() == 0)
    {
        string typeName = symPtr->type()->name()->c_str();
        throw logic_error(typeName + ": could not get pointed object");
    }
    RefPtr<DebugSymbol> obj = symPtr->nth_child(0);

    return CHKPTR(obj);
}

RefPtr<DebugSymbol>
PostfixExpr::eval_pointer(Context& ctxt, const Variant& lval)
{
    assert(ident_.get());

    // first, evaluate the expression left of '->', which
    // should yield a either pointer-type, or a class instance
    RefPtr<Variant> tmp = expr_->eval(ctxt);
    if (!tmp)
    {
        throw logic_error("base operand of -> yielded null");
    }
    if (!expr_->type())
    {
        throw logic_error("null expression type");
    }
    check_for_operator_arrow(ctxt, tmp);
    return eval_pointer(ctxt, expr_, tmp);
}

static void
enforce_integer_type(const Variant& var, const Expr& param)
{
    if (!is_integer(var))
    {
        string err("invalid type ");

        if (RefPtr<DataType> type = param.type())
        {
            err += CHKPTR(type->name())->c_str();
            err += " ";
        }
        err += "for array subscript";
        throw EvalError(err);
    }
}

static uint64_t
array_size(DebugSymbol* array, const ArrayType* arrayType)
{
    uint64_t upper = numeric_limits<int64_t>::max();

    if (const DynamicArrayType* dynArray =
            interface_cast<const DynamicArrayType*>(arrayType))
    {
        upper = dynArray->count(array);
    }
    else if (arrayType)
    {
        // array of fixed size
        upper = arrayType->elem_count();
    }
    return upper;
}

/**
 * Helper function, extract index value from variant, and
 * check bounds
 */
static uint64_t
get_index(const Variant&    index,
          DebugSymbol*      array = 0,
          const ArrayType*  arrayType = 0)
{
    uint64_t result = 0;
    const uint64_t upper = array_size(array, arrayType);

    if (index.type_tag() == Variant::VT_UINT64)
    {
        if (index.uint64() >= upper)
        {
            throw range_error("array subscript is out of range");
        }
        result = index.uint64();
    }
    else
    {
        //
        // no negative indices allowed in C/C++
        //
        if ((index.int64() < 0) ||
            (static_cast<uint64_t>(index.int64()) >= upper)
           )
        {
            throw range_error("array subscript is out of range");
        }
        result = index.int64();
    }
    return result;
}

RefPtr<Variant>
PostfixExpr::eval_array_range(Context& ctxt, const Variant& lval)
{
    DataType* type = CHKPTR(expr_)->type().get();
    ArrayType* arrayType = interface_cast<ArrayType*>(type);
    if (!arrayType)
    {
        throw EvalError("base operand of [:] is not an array");
    }

    // must have an argument list by grammar rules
    ExprList args = interface_cast<ArgumentList&>(*CHKPTR(param_)).args();
    if (args.size() != 2)
    {
        throw logic_error("unexpected range specification");
    }

    RefPtr<DebugSymbol> sym = lval.debug_symbol();

    uint64_t low = 0, high = 0;

    if (args[0])
    {
        low = get_index(*args[0]->eval(ctxt), sym.get(), arrayType);
    }
    if (args[1])
    {
        high = get_index(*args[1]->eval(ctxt), sym.get(), arrayType);
        if (high)
        {
            --high;
        }
    }
    if (low >= high)
    {
        high = array_size(sym.get(), arrayType);
        if (high)
        {
            --high; // the highest valid index in the array
        }
    }
    RefPtr<DataType> elemType = CHKPTR(arrayType->elem_type());
    RefPtr<DataType> resultType =
        ctxt.type_system().get_array_type(low, high, elemType.get());

    addr_t addr = arrayType->first_elem_addr(sym.get());

    if (addr)
    {
        addr += elemType->size() * low;
    }
    RefPtr<DebugSymbol> newSym =
        ctxt.type_system().create_debug_symbol(
                sym->reader(),
                sym->thread(),
                resultType.get(),
                sym->name(),
                addr,
                NULL,   //sym->decl_file(),
                0,      //sym->decl_line(),
                sym->is_return_value());
    newSym->read(&ctxt);

    if (addr == 0)
    {
        // support synthesised arrays
        newSym->read(&ctxt);
        Slicer slicer(sym);
        slicer.run(low, high, newSym);

        interface_cast<DebugSymbolImpl&>(*newSym).set_value(sym->value());
    }

    set_type(resultType);
    return new VariantImpl(*newSym);
}

RefPtr<Variant>
PostfixExpr::eval_array(Context& ctxt, const Variant& lval)
{
    if ((lval.type_tag() != Variant::VT_ARRAY)
     && (lval.type_tag() != Variant::VT_POINTER))
    {
        throw EvalError("base operand of [] is not pointer or array");
    }

    if (!param_)
    {
        // at this point a non-null subscript expression is expected
        throw logic_error("null subscript expression");
    }
    RefPtr<Variant> rval = param_->eval(ctxt);
    // expect the evalution to succeed and to yield an integer result
    if (!rval)
    {
        throw logic_error("subscript expression yielded null");
    }
    enforce_integer_type(*rval, *param_);

    RefPtr<DebugSymbol> sym;

    DataType* type = expr_->type().get();
    if (PointerType* ptrType = interface_cast<PointerType*>(type))
    {
        if (ptrType->is_reference())
        {
            throw EvalError("base operand of [] is not an array");
        }
        RefPtr<DebugSymbol> ptr = CHKPTR(lval.debug_symbol());
        ptr->read(&ctxt);

        if (RefPtr<DebugSymbolImpl> elem =
            interface_cast<DebugSymbolImpl*>(ptr->nth_child(0)))
        {
            const size_t elemSize = CHKPTR(elem->type())->size();
            const addr_t addr = elem->addr();

            elem->set_addr(addr + elemSize * get_index(*rval));

            elem->read(&ctxt);
            sym = elem;
        }
    }
    else
    {
        ArrayType* arrayType = interface_cast<ArrayType*>(type);
        if (!arrayType)
        {
            if (interface_cast<AssociativeContainerType*>(type))
            {
                throw runtime_error("subscript not supported in associative containers");
            }
        #if DEBUG
            clog << type->name() << ": not an array\n";
        #endif
            throw EvalError("base operand of [] is not an array");
        }

        uint64_t index = get_index(*rval, lval.debug_symbol(), arrayType);

        if (!lval.debug_symbol())
        {
            throw logic_error("null array symbol");
        }
        lval.debug_symbol()->read(&ctxt);
        sym = lval.debug_symbol()->nth_child(index);
    }
    set_type(sym->type());

    return new VariantImpl(*sym);
}

RefPtr<Variant>
PostfixExpr::eval_function_call(Context& ctxt, Variant& lval)
{
    ctxt.reset_frame_setup();
    if (DebugSymbol* fun = lval.debug_symbol())
    {
        assert (!interface_cast<MacroType*>(fun->type()));
        // function calls are evaluated asynchronously,
        // therefore there is no return value here
        eval_function_call(ctxt, *fun);
        DEBUG_OUT << fun->name() << endl;
    }
    else
    {
        throw logic_error("null function symbol in function call");
    }
    return RefPtr<Variant>();
}

RefPtr<CallSetup>
PostfixExpr::get_overloaded_operator(Context& ctxt, bool strict)
{
    RefPtr<CallSetup> result;

    RefPtr<ClassType> klass = interface_cast<ClassType>(expr_->type());
    if (klass.get())
    {
        string opname = "operator";
        switch (oper_)
        {
        case ARRAY: opname += "[]"; break;
        case FCALL: opname += "()"; break;
        case POINTER: opname += "->"; break;
        case INC: opname+= "++"; break;
        case DEC: opname+= "--"; break;
        default: return NULL;
        }

        RefPtr<DebugSymbol> fun = lookup_methods(ctxt, *klass, opname);
        if (!fun)
        {
            if (!strict)
            {
                return result;
            }
            const char* kname = CHKPTR(klass->name())->c_str();
            throw EvalError(opname + " not found in: " + kname);
        }

        ExprList args;

        // push the hidden "this" parameter onto the stack
        args.push_back(
            new UnaryExpr(interp().get(),
                          UnaryExpr::ADDR,
                          expr_,
                          UnaryExpr::INTERNAL));
        switch (oper_)
        {
        case INC:
        case DEC:
            {
                // postfix operators take a dummy int parameter
                RefPtr<DataType> intType(ctxt.get_int_type());
                RefPtr<DebugSymbol> dummy(ctxt.new_const(*intType, "0xdead"));
                args.push_back(new Ident(interp().get(), "", dummy));
            }
            break;

        case ARRAY:
            assert(param_.get());
            args.push_back(param_);
            break;

        case FCALL:
            {
                ExprList& param =
                    interface_cast<ArgumentList&>(*param_).args();
                args.insert(args.end(), param.begin(), param.end());
            }
            break;

        default:
            break;
        }

        result = get_call_setup(ctxt, *this, fun.get(), &args);
        if (!result)
        {
            no_matching_func(ctxt, *fun, &args); // emit error
        }
        else if (oper_ == INC || oper_ == DEC)
        {
            // int argument is used for signature only,
            // not passed to operator
            if (result->args().size() == 2)
            {
                result->args().pop_back();
            }
        }
    }
    return result;
}

void
PostfixExpr::eval_function_call(Context& ctxt, DebugSymbol& fun)
{
#if !defined(__i386__) && !defined(__x86_64__) // fixme
    throw runtime_error(__func__ + string(": not implemented on this platform"));
#endif
    ctxt.reset_frame_setup();

// gcc 2.95 bug workaround
#if !defined(DEBUG) && (__GNUC__ < 3)
  // I don't know why, but this somehow prevents the 2.95 compiler
  // from crashing, when in release (optimizing) mode
  try
  {
#endif

    ExprList args;
    if (param_) // function call has arguments?
    {
        args = interface_cast<ArgumentList&>(*param_).args();
    }

    RefPtr<CallSetup> setup;
    Method* method = interface_cast<Method*>(&fun);

    DEBUG_OUT << fun.name() << " *** method=" << method << " ***\n";

    if (method && !method->is_static())
    {
        DEBUG_OUT << "trying member functions\n";
        setup = get_method(ctxt, fun, &args);
    }
    else
    {
        setup = get_call_setup(ctxt, *this, &fun, &args);
        // <workaround bug in STABS reader>
        if (!setup && method)
        {
            setup = get_method(ctxt, fun, &args);
        }
        // </workaround>
    }
    if (!setup)
    {
        no_matching_func(ctxt, fun, &args);
    }
    else
    {
        assert(setup->reader() == fun.reader()); // post-condition
    }

    initiate_fun_call(ctxt, *setup);

// gcc 2.95 bug workaround
#if !defined(DEBUG) && (__GNUC__ < 3)
  }
  catch (...)
  {
    throw;
  }
#endif
}

RefPtr<CallSetup>
PostfixExpr::get_method(Context& ctxt,
                        DebugSymbol& fun,
                        ExprList* args)
{
    // add the hidden `this' parameter to the arg list
    RefPtr<Expr> thisPtr;

    if (PostfixExpr* pfix = interface_cast<PostfixExpr*>(expr_.get()))
    {
        // the hidden THIS parameter
        switch (pfix->oper())
        {
        case POINTER:
        case VPOINTER:
            if (!pfix->ptr_)
            {
                thisPtr = pfix->expr_;
            }
            else
            {
                thisPtr = pfix->ptr_;
            }
            break;

        case MEMBER:
            thisPtr = new UnaryExpr(this->interp().get(),
                                    UnaryExpr::ADDR,
                                    pfix->expr_,
                                    UnaryExpr::INTERNAL);
        default:
            break;
        }
    }
    RefPtr<CallSetup> setup;

    if (thisPtr)
    {
        if (!param_)
        {
            RefPtr<ArgumentList> param =
                new ArgumentList(interp().get(), thisPtr);
            param_ = param;
            args = &param->args();
        }
        else
        {
            assert(args);
            args->insert(args->begin(), thisPtr);
        }
        setup = get_call_setup(ctxt, *this, &fun, args);
    }
    return setup;
}

void
PostfixExpr::initiate_fun_call(Context& ctxt, CallSetup& setup)
{
    set_strict_type(setup.is_return_type_strict());

    if (Thread* thread = ctxt.thread())
    {
        if (Debugger* dbg = thread->debugger())
        {
            dbg->set_breakpoint_at_throw(thread, false);
        }
    }
    // Context::call_function does not return, so if there are
    // any other things to setup, here is the place to do it
    // ...

    ctxt.call_function(setup);
}

void
PostfixExpr::map_arguments(const string& params, ArgMap& argMap)
{
    typedef boost::char_separator<char> Delim;
    typedef boost::tokenizer<Delim> Tokenizer;

    // tokenize macro arguments and map them to the
    // expressions that are then passed as arguments
    // to the call
    Delim delimiters(", )");
    Tokenizer tok(params, delimiters);
    ExprList args;
    if (Expr* param = param_.get()) // the call has arguments?
    {
        ArgumentList& alist = interface_cast<ArgumentList&>(*param);
        args = alist.args();
    }

    Tokenizer::const_iterator i = tok.begin();
    const Tokenizer::const_iterator end = tok.end();
    ExprList::const_iterator j = args.begin();
    for (; i != end; ++i, ++j)
    {
        if (j == args.end())
        {
            throw runtime_error("macro argument missing");
        }
        argMap.insert(make_pair(*i, *j));
    }
    if (j != args.end())
    {
        throw runtime_error("too many macro arguments");
    }
    isMacroCall_ = true;
}

class ZDK_LOCAL PointerExprHelper : public PostfixExpr
{
    RefPtr<PostfixExpr> pfix_;

public:
    PointerExprHelper(Interp* in, const RefPtr<PostfixExpr>& expr)
    : PostfixExpr(in, POINTER, expr, expr->param())
    , pfix_(expr)
    { }

private:
    virtual void set_result(const RefPtr<Variant>& var)
    {
        PostfixExpr::set_result(var);
        pfix_->set_result(var);
    }

    virtual void set_ptr(const RefPtr<Expr>& ptr)
    {
        PostfixExpr::set_ptr(ptr);
        pfix_->set_ptr(ptr);
    }

    RefPtr<Variant> eval_impl(Context& ctxt)
    {
        RefPtr<Variant> var(expr()->value());
        check_for_operator_arrow(ctxt, var);

        RefPtr<DebugSymbol> sym(pfix_->eval_pointer(ctxt, pfix_, var));

        DEBUG_OUT << "sym=" << hex << sym->addr() << dec << endl;
        RefPtr<Interp> interp = expr()->interp();
        RefPtr<Expr> ptr(expr()->clone(interp.get()));
        ptr->set_result(expr()->value());
        pfix_->set_ptr(ptr);

        if (sym.get())
        {
            const string name = CHKPTR(pfix_->ident())->name();
            var = pfix_->eval_member(ctxt, *sym, name, true);

            pfix_->set_result(var);
            DEBUG_OUT << "done: " << pfix_->type()->name() << endl;
        }
        return var;
    }
};

/**
 * @note return void since initiate_fun_call never returns
 */
void
PostfixExpr::check_for_operator_arrow(Context& ctxt, RefPtr<Variant> tmp)
{
    if (tmp->type_tag() == Variant::VT_OBJECT)
    {
        DEBUG_OUT << expr_->type()->name() << endl;
        RefPtr<CallSetup> setup(get_overloaded_operator(ctxt, true));
        if (setup.get())
        {
            DEBUG_OUT << "overloaded operator->()\n";

            // push the helper on the stack, so that Interp::resume()
            // will pick it up, and the evaluation of the pointer
            // expression continues
            RefPtr<Expr> expr(new PointerExprHelper(interp().get(), this));
            ctxt.push(expr);

            initiate_fun_call(ctxt, *setup);
        }
    }
}

RefPtr<Expr> PostfixExpr::clone(Interp* in) const
{
    DEBUG_OUT << "interp=" << in << endl;

    RefPtr<Expr> param(param_ ? param_->clone(in) : 0);
    return new PostfixExpr(in, oper_, expr_->clone(in), param);
}

ArgumentList::ArgumentList(Interp* interp, const RefPtr<Expr>& expr)
    : Expr(interp)
{
    args_.push_back(expr);
}

ArgumentList::~ArgumentList() throw()
{
}

RefPtr<Variant> ArgumentList::eval_impl(Context& context)
{
    // each argument should be evaluated separately
    throw logic_error("unexpected request to evaluate arg list");

    return RefPtr<Variant>(); // keep compiler happy
}
// vim: tabstop=4:softtabstop=4:expandtab:shiftwidth=4

max_stars_repo_name: cristivlas/zerobugs

max_issues_repo_name: cristivlas/zerobugs

max_forks_repo_name: cristivlas/zerobugs


text:
/*-----------------------------------------------------------------------------+
Copyright (c) 2008-2009: Joachim Faulhaber
+------------------------------------------------------------------------------+
   Distributed under the Boost Software License, Version 1.0.
      (See accompanying file LICENCE.txt or copy at
           http://www.boost.org/LICENSE_1_0.txt)
+-----------------------------------------------------------------------------*/
#define BOOST_TEST_MODULE icl::interval_map_mixed unit test
#include <libs/icl/test/disable_test_warnings.hpp>
#include <string>
#include <boost/mpl/list.hpp>
#include "../unit_test_unwarned.hpp"
#include <boost/test/test_case_template.hpp>

// interval instance types
#include "../test_type_lists.hpp"
#include "../test_value_maker.hpp"

#include <boost/icl/interval_set.hpp>
#include <boost/icl/separate_interval_set.hpp>
#include <boost/icl/split_interval_set.hpp>
#include <boost/icl/interval_map.hpp>
#include <boost/icl/split_interval_map.hpp>

using namespace std;
using namespace boost;
using namespace unit_test;
using namespace boost::icl;

#include "../test_interval_map_mixed.hpp"

BOOST_AUTO_TEST_CASE
(fastest_icl_interval_map_mixed_ctor_4_ordered_types)
{            interval_map_mixed_ctor_4_ordered_types<std::string, int>(); }

BOOST_AUTO_TEST_CASE
(fastest_icl_interval_map_mixed_equal_4_ordered_types)
{            interval_map_mixed_equal_4_ordered_types<double, int>(); }

BOOST_AUTO_TEST_CASE
(fastest_icl_interval_map_mixed_assign_4_ordered_types)
{            interval_map_mixed_assign_4_ordered_types<unsigned int, int>(); }

BOOST_AUTO_TEST_CASE
(fastest_icl_interval_map_mixed_ctor_4_bicremental_types)
{            interval_map_mixed_ctor_4_bicremental_types<bicremental_type_1, int>(); }

BOOST_AUTO_TEST_CASE
(fastest_icl_interval_map_mixed_assign_4_bicremental_types)
{            interval_map_mixed_assign_4_bicremental_types<bicremental_type_2, int>(); }

BOOST_AUTO_TEST_CASE
(fastest_icl_interval_map_mixed_equal_4_bicremental_types)
{            interval_map_mixed_equal_4_bicremental_types<bicremental_type_3, int>(); }

BOOST_AUTO_TEST_CASE
(fastest_itl_partial_interval_map_mixed_inclusion_compare_4_bicremental_types)
{            partial_interval_map_mixed_inclusion_compare_4_bicremental_types<bicremental_type_4, int, partial_absorber>(); }

BOOST_AUTO_TEST_CASE
(fastest_itl_partial_interval_map_mixed_contains_4_bicremental_types)
{            partial_interval_map_mixed_contains_4_bicremental_types<int, int, partial_absorber>(); }


text:
/**
 * Extract features and score statistics from nvest file, optionally merging with
 * those from the previous iteration.
 * Developed during the 2nd MT marathon.
 **/

#include <iostream>
#include <string>
#include <vector>

#include <getopt.h>
#include <boost/scoped_ptr.hpp>

#include "Data.h"
#include "Scorer.h"
#include "ScorerFactory.h"
#include "Timer.h"
#include "Util.h"

using namespace std;
using namespace MosesTuning;

namespace {

void usage()
{
  cerr << "usage: extractor [options])" << endl;
  cerr << "[--sctype|-s] the scorer type (default BLEU)" << endl;
  cerr << "[--scconfig|-c] configuration string passed to scorer" << endl;
  cerr << "\tThis is of the form NAME1:VAL1,NAME2:VAL2 etc " << endl;
  cerr << "[--reference|-r] comma separated list of reference files" << endl;
  cerr << "[--binary|-b] use binary output format (default to text )" << endl;
  cerr << "[--nbest|-n] the nbest file" << endl;
  cerr << "[--scfile|-S] the scorer data output file" << endl;
  cerr << "[--ffile|-F] the feature data output file" << endl;
  cerr << "[--prev-ffile|-E] comma separated list of previous feature data" << endl;
  cerr << "[--prev-scfile|-R] comma separated list of previous scorer data" << endl;
  cerr << "[--factors|-f] list of factors passed to the scorer (e.g. 0|2)" << endl;
  cerr << "[--filter|-l] filter command used to preprocess the sentences" << endl;
  cerr << "[--allow-duplicates|-d] omit the duplicate removal step" << endl;
  cerr << "[-v] verbose level" << endl;
  cerr << "[--help|-h] print this message and exit" << endl;
  exit(1);
}

static struct option long_options[] = {
  {"sctype", required_argument, 0, 's'},
  {"scconfig", required_argument,0, 'c'},
  {"factors", required_argument,0, 'f'},
  {"filter", required_argument,0, 'l'},
  {"reference", required_argument, 0, 'r'},
  {"binary", no_argument, 0, 'b'},
  {"nbest", required_argument, 0, 'n'},
  {"scfile", required_argument, 0, 'S'},
  {"ffile", required_argument, 0, 'F'},
  {"prev-scfile", required_argument, 0, 'R'},
  {"prev-ffile", required_argument, 0, 'E'},
  {"verbose", required_argument, 0, 'v'},
  {"help", no_argument, 0, 'h'},
  {"allow-duplicates", no_argument, 0, 'd'},
  {0, 0, 0, 0}
};

// Command line options used in extractor.
struct ProgramOption {
  string scorerType;
  string scorerConfig;
  string scorerFactors;
  string scorerFilter;
  string referenceFile;
  string nbestFile;
  string scoreDataFile;
  string featureDataFile;
  string prevScoreDataFile;
  string prevFeatureDataFile;
  bool binmode;
  bool allowDuplicates;
  int verbosity;

  ProgramOption()
      : scorerType("BLEU"),
        scorerConfig(""),
        scorerFactors(""),
        scorerFilter(""),
        referenceFile(""),
        nbestFile(""),
        scoreDataFile("statscore.data"),
        featureDataFile("features.data"),
        prevScoreDataFile(""),
        prevFeatureDataFile(""),
        binmode(false),
        allowDuplicates(false),
        verbosity(0) { }
};

void ParseCommandOptions(int argc, char** argv, ProgramOption* opt) {
  int c;
  int option_index;

  while ((c = getopt_long(argc, argv, "s:r:f:l:n:S:F:R:E:v:hbd", long_options, &option_index)) != -1) {
    switch (c) {
      case 's':
        opt->scorerType = string(optarg);
        break;
      case 'c':
        opt->scorerConfig = string(optarg);
        break;
      case 'f':
        opt->scorerFactors = string(optarg);
        break;
      case 'l':
        opt->scorerFilter = string(optarg);
        break;
      case 'r':
        opt->referenceFile = string(optarg);
        break;
      case 'b':
        opt->binmode = true;
        break;
      case 'n':
        opt->nbestFile = string(optarg);
        break;
      case 'S':
        opt->scoreDataFile = string(optarg);
        break;
      case 'F':
        opt->featureDataFile = string(optarg);
        break;
      case 'E':
        opt->prevFeatureDataFile = string(optarg);
        break;
      case 'R':
        opt->prevScoreDataFile = string(optarg);
        break;
      case 'v':
        opt->verbosity = atoi(optarg);
        break;
      case 'd':
        opt->allowDuplicates = true;
        break;
      default:
        usage();
    }
  }
}

} // anonymous namespace

int main(int argc, char** argv)
{
  ResetUserTime();

  ProgramOption option;
  ParseCommandOptions(argc, argv, &option);

  try {
    // check whether score statistics file is specified
    if (option.scoreDataFile.length() == 0) {
      throw runtime_error("Error: output score statistics file is not specified");
    }

    // check wheter feature file is specified
    if (option.featureDataFile.length() == 0) {
      throw runtime_error("Error: output feature file is not specified");
    }

    // check whether reference file is specified when nbest is specified
    if ((option.nbestFile.length() > 0 && option.referenceFile.length() == 0)) {
      throw runtime_error("Error: reference file is not specified; you can not score the nbest");
    }

    vector<string> nbestFiles;
    if (option.nbestFile.length() > 0) {
      Tokenize(option.nbestFile.c_str(), ',', &nbestFiles);
    }

    vector<string> referenceFiles;
    if (option.referenceFile.length() > 0) {
      Tokenize(option.referenceFile.c_str(), ',', &referenceFiles);
    }

    vector<string> prevScoreDataFiles;
    if (option.prevScoreDataFile.length() > 0) {
      Tokenize(option.prevScoreDataFile.c_str(), ',', &prevScoreDataFiles);
    }

    vector<string> prevFeatureDataFiles;
    if (option.prevFeatureDataFile.length() > 0) {
      Tokenize(option.prevFeatureDataFile.c_str(), ',', &prevFeatureDataFiles);
    }

    if (prevScoreDataFiles.size() != prevFeatureDataFiles.size()) {
      throw runtime_error("Error: there is a different number of previous score and feature files");
    }

    if (option.binmode) {
      cerr << "Binary write mode is selected" << endl;
    } else {
      cerr << "Binary write mode is NOT selected" << endl;
    }

    TRACE_ERR("Scorer type: " << option.scorerType << endl);

    boost::scoped_ptr<Scorer> scorer(
        ScorerFactory::getScorer(option.scorerType, option.scorerConfig));

    // set Factors and Filter used to preprocess the sentences
    scorer->setFactors(option.scorerFactors);
    scorer->setFilter(option.scorerFilter);

    // load references
    if (referenceFiles.size() > 0)
      scorer->setReferenceFiles(referenceFiles);

//    PrintUserTime("References loaded");

    Data data(scorer.get());

    // load old data
    for (size_t i = 0; i < prevScoreDataFiles.size(); i++) {
      data.load(prevFeatureDataFiles.at(i), prevScoreDataFiles.at(i));
    }

//    PrintUserTime("Previous data loaded");

    // computing score statistics of each nbest file
    for (size_t i = 0; i < nbestFiles.size(); i++) {
      data.loadNBest(nbestFiles.at(i));
    }

//    PrintUserTime("Nbest entries loaded and scored");

    //ADDED_BY_TS
    if (!option.allowDuplicates) {
      data.removeDuplicates();
    }
    //END_ADDED

    data.save(option.featureDataFile, option.scoreDataFile, option.binmode);
    PrintUserTime("Stopping...");

    return EXIT_SUCCESS;
  } catch (const exception& e) {
    cerr << "Exception: " << e.what() << endl;
    return EXIT_FAILURE;
  }
}

max_stars_repo_name: anshsarkar/TailBench

max_issues_repo_name: anshsarkar/TailBench

max_forks_repo_name: anshsarkar/TailBench