/*
 *
 * Copyright (c) 1998-9
 * Dr John Maddock
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Dr John Maddock makes no representations
 * about the suitability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 *
 */

 /*
  *   FILE     regex.h
  *   VERSION  2.12
  */


/* start with C compatability API */

#ifndef __REGEX_H
#define __REGEX_H

#include <cregex>

#ifdef __cplusplus

// what follows is all C++ don't include in C builds!!

#include <new.h>
#if !defined(JM_NO_TYPEINFO)
#include <typeinfo>
#endif
#include <string.h>
#include <jm/jstack.h>
#include <jm/re_raw.h>
#include <jm/re_nls.h>
#include <jm/regfac.h>
#include <jm/re_cls.h>
#include <jm/re_coll.h>
#include <jm/re_kmp.h>


JM_NAMESPACE(__JM)

//
// define error hanling classes
#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_EXCEPTION_H)
// standard classes are available:

class JM_IX_DECL bad_expression : public __JM_STD::exception
{
#ifdef RE_LOCALE_CPP
   __JM_STD::string code;
public:
   bad_expression(const __JM_STD::string& s) : code(s) {}
#else
   unsigned int code;
public:
   bad_expression(unsigned int err) : code(err) {}
#endif
   bad_expression(const bad_expression& e) : __JM_STD::exception(e), code(e.code) {}
   bad_expression& operator=(const bad_expression& e)
   {
      #ifdef _MSC_VER
      static_cast<__JM_STD::exception*>(this)->operator=(e);
      #else
      __JM_STD::exception::operator=(e);
      #endif
      code = e.code;
      return *this;
   }
   virtual const char* what()const throw();
};

#elif !defined(JM_NO_EXCEPTIONS)
// no standard classes, do it ourselves:

class JM_IX_DECL bad_expression
{
#ifdef RE_LOCALE_CPP
   __JM_STD::string code;
public:
   bad_expression(const __JM_STD::string& s) : code(s) {}
#else
   unsigned int code;
public:
   bad_expression(unsigned int err) : code(err) {}
#endif
   bad_expression(const bad_expression& e) : code(e.code) {}
   bad_expression& operator=(const bad_expression& e) { code = e.code; return *this; }
   virtual const char* what()const throw();
};

#endif

//
// define default traits classes for char and wchar_t types:
//

struct re_set_long;
struct re_syntax_base;

enum char_syntax_type
{
   syntax_char = 0,
   syntax_open_bracket = 1,                  // (
   syntax_close_bracket = 2,                 // )
   syntax_dollar = 3,                        // $
   syntax_caret = 4,                         // ^
   syntax_dot = 5,                           // .
   syntax_star = 6,                          // *
   syntax_plus = 7,                          // +
   syntax_question = 8,                      // ?
   syntax_open_set = 9,                      // [
   syntax_close_set = 10,                    // ]
   syntax_or = 11,                           // |
   syntax_slash = 12,                        //
   syntax_hash = 13,                         // #
   syntax_dash = 14,                         // -
   syntax_open_brace = 15,                   // {
   syntax_close_brace = 16,                  // }
   syntax_digit = 17,                        // 0-9
   syntax_b = 18,                            // for \b
   syntax_B = 19,                            // for \B
   syntax_left_word = 20,                    // for \<
   syntax_right_word = 21,                   // for \>
   syntax_w = 22,                            // for \w
   syntax_W = 23,                            // for \W
   syntax_start_buffer = 24,                 // for \`
   syntax_end_buffer = 25,                   // for \'
   syntax_newline = 26,                      // for newline alt
   syntax_comma = 27,                        // for {x,y}

   syntax_a = 28,                            // for \a
   syntax_f = 29,                            // for \f
   syntax_n = 30,                            // for \n
   syntax_r = 31,                            // for \r
   syntax_t = 32,                            // for \t
   syntax_v = 33,                            // for \v
   syntax_x = 34,                            // for \xdd
   syntax_c = 35,                            // for \cx
   syntax_colon = 36,                        // for [:...:]
   syntax_equal = 37,                        // for [=...=]
   
   // perl ops:
   syntax_e = 38,                            // for \e
   syntax_l = 39,                            // for \l
   syntax_L = 40,                            // for \L
   syntax_u = 41,                            // for \u
   syntax_U = 42,                            // for \U
   syntax_s = 43,                            // for \s
   syntax_S = 44,                            // for \S
   syntax_d = 45,                            // for \d
   syntax_D = 46,                            // for \D
   syntax_E = 47,                            // for \Q\E
   syntax_Q = 48,                            // for \Q\E
   syntax_X = 49,                            // for \X
   syntax_C = 50,                            // for \C
   syntax_Z = 51,                            // for \Z
   syntax_G = 52,                            // for \G

   syntax_max = 53
};

template <class charT>
class char_regex_traits
{
public:
   typedef charT char_type;
   //
   // uchar_type is the same size as char_type
   // but must be unsigned:
   typedef charT uchar_type;
   //
   // size_type is normally the same as charT
   // but could be unsigned int to improve performance
   // of narrow character types, NB must be unsigned:
   typedef jm_uintfast32_t size_type;

   // length:
   // returns the length of a null terminated string
   // can be left unimplimented for non-character types.
   static size_t length(const char_type* );

   // syntax_type
   // returns the syntax type of a given charT
   // translates customised syntax to a unified enum.
   static unsigned int syntax_type(size_type c);

   // translate:
   //
   static charT RE_CALL translate(charT c, bool icase
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale&
   #endif
   );

   // transform:
   //
   // converts a string into a sort key for locale dependant
   // character ranges.
   static void RE_CALL transform(re_str<charT>& out, const re_str<charT>& in
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale&
   #endif
   );

   // transform_primary:
   //
   // converts a string into a primary sort key for locale dependant
   // equivalence classes.
   static void RE_CALL transform_primary(re_str<charT>& out, const re_str<charT>& in
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale&
   #endif
   );

   // is_separator
   // returns true if c is a newline character
   static bool RE_CALL is_separator(charT c);

   // is_combining
   // returns true if the character is a unicode
   // combining character
   static bool RE_CALL is_combining(charT c);

   // is_class
   // returns true if the character is a member
   // of the specified character class
   static bool RE_CALL is_class(charT c, jm_uintfast32_t f
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale&
   #endif
   );

   // toi
   // converts c to integer
   static int RE_CALL toi(charT c
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale&
   #endif
   );

   // toi
   // converts multi-character value to int
   // updating first as required
   static int RE_CALL toi(const charT*& first, const charT* last, int radix
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale&
   #endif
   );

   // lookup_classname
   // parses a class declaration of the form [:class:]
   // On entry first points to the first character of the class name.
   // 
   static jm_uintfast32_t RE_CALL lookup_classname(const charT* first, const charT* last
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale&
   #endif
   );

   // lookup_collatename
   // parses a collating element declaration of the form [.collating_name.]
   // On entry first points to the first character of the collating element name.
   // 
   static bool RE_CALL lookup_collatename(re_str<charT>& s, const charT* first, const charT* last
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale&
   #endif
   );

};

JM_TEMPLATE_SPECIALISE
class char_regex_traits<char>
{
public:
   typedef char char_type;
   typedef unsigned char uchar_type;
   typedef unsigned int size_type;
   static size_t RE_CALL length(const char_type* p)
   {
      return strlen(p);
   }
   static unsigned int RE_CALL syntax_type(size_type c
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      return JM_USE_FACET(l, regfacet<char>).syntax_type((char)c);
      #else
      return re_syntax_map[c];
      #endif
   }
   static char RE_CALL translate(char c, bool icase
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      return icase ? JM_USE_FACET(l, __JM_STD::ctype<char>).tolower((char_type)c) : c;
      #else
      return icase ? re_lower_case_map[(size_type)(uchar_type)c] : c;
      #endif
   }
   static void RE_CALL transform(re_str<char>& out, const re_str<char>& in
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
#ifndef RE_LOCALE_CPP
      re_transform(out, in);
#else
      out = JM_USE_FACET(l, __JM_STD::collate<char>).transform(in.c_str(), in.c_str() + in.size()).c_str();
#endif
   }

   static void RE_CALL transform_primary(re_str<char>& out, const re_str<char>& in
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      transform(out, in MAYBE_PASS_LOCALE(l));
#ifdef RE_LOCALE_W32
      re_trunc_primary(out);
#else
      unsigned n = in.size() + out.size() / 4;
      if(n < out.size())
         out[n] = 0;
#endif
   }

   static bool RE_CALL is_separator(char c)
   {
      return JM_MAKE_BOOL((c == '\n') || (c == '\r'));
   }

   static bool RE_CALL is_combining(char)
   {
      return false;
   }
   
   static bool RE_CALL is_class(char c, jm_uintfast32_t f
#ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
#endif
   )
   {
      #ifdef RE_LOCALE_CPP
      if(JM_USE_FACET(l, __JM_STD::ctype<char>).is((__JM_STD::ctype<char>::mask)(f & char_class_all_base), c))
         return true;
      if((f & char_class_underscore) && (c == '_'))
         return true;
      if((f & char_class_blank) && ((c == ' ') || (c == '\t')))
         return true;
      return false;
      #else
      return JM_MAKE_BOOL(re_class_map[(size_type)(uchar_type)c] & f);
      #endif
   }
   static int RE_CALL toi(char c
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      return re_toi(c MAYBE_PASS_LOCALE(l));
   }
   static int RE_CALL toi(const char*& first, const char* last, int radix
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      return re_toi(first, last, radix MAYBE_PASS_LOCALE(l));
   }

   static jm_uintfast32_t RE_CALL lookup_classname(const char* first, const char* last
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      return JM_USE_FACET(l, regfacet<char>).lookup_classname(first, last);
      #else
      return re_lookup_class(first, last);
      #endif
   }

   static bool RE_CALL lookup_collatename(re_str<char>& s, const char* first, const char* last
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      re_str<char> n(first, last);
      return JM_USE_FACET(l, regfacet<char>).lookup_collatename(s, n);
      #else
      return re_lookup_collate(s, first, last);
      #endif
   }
};

#ifndef JM_NO_WCSTRING
JM_TEMPLATE_SPECIALISE
class char_regex_traits<wchar_t>
{
public:
   typedef wchar_t char_type;
   typedef unsigned short uchar_type;
   typedef unsigned int size_type;
   static size_t RE_CALL length(const char_type* p)
   {
      return wcslen(p);
   }
   static unsigned int RE_CALL syntax_type(size_type c
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      return JM_USE_FACET(l, regfacet<wchar_t>).syntax_type((wchar_t)c);
      #else
      return re_get_syntax_type(c);
      #endif
   }
   static wchar_t RE_CALL translate(wchar_t c, bool icase
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      return icase ? JM_USE_FACET(l, __JM_STD::ctype<wchar_t>).tolower((char_type)c) : c;
      #else
      return icase ? ((c < 256) ? re_lower_case_map_w[(uchar_type)c] : re_wtolower(c)) : c;
      #endif
   }

   static void RE_CALL transform(re_str<wchar_t>& out, const re_str<wchar_t>& in
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
#ifndef RE_LOCALE_CPP
      re_transform(out, in);
#else
      out = JM_USE_FACET(l, __JM_STD::collate<wchar_t>).transform(in.c_str(), in.c_str() + in.size()).c_str();
#endif
   }

   static void RE_CALL transform_primary(re_str<wchar_t>& out, const re_str<wchar_t>& in
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      transform(out, in MAYBE_PASS_LOCALE(l));
#ifdef RE_LOCALE_W32
      re_trunc_primary(out);
#else
      unsigned n = in.size() + out.size() / 4;
      if(n < out.size())
         out[n] = 0;
#endif
   }

   static bool RE_CALL is_separator(wchar_t c)
   {
      return JM_MAKE_BOOL((c == L'\n') || (c == L'\r') || (c == (wchar_t)0x2028) || (c == (wchar_t)0x2029));
   }

   static bool RE_CALL is_combining(wchar_t c)
   {
      return re_is_combining(c);
   }
   
   static bool RE_CALL is_class(wchar_t c, jm_uintfast32_t f
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      if(JM_USE_FACET(l, __JM_STD::ctype<wchar_t>).is((__JM_STD::ctype<wchar_t>::mask)(f & char_class_all_base), c))
         return true;
      if((f & char_class_underscore) && (c == '_'))
         return true;
      if((f & char_class_blank) && ((c == ' ') || (c == '\t')))
         return true;
      if((f & char_class_unicode) && (c > (size_type)(uchar_type)255))
         return true;
      return false;
      #else
      return JM_MAKE_BOOL(((uchar_type)c < 256) ? (re_unicode_classes[(size_type)(uchar_type)c] & f) : re_iswclass(c, f));
      #endif
   }
   static int RE_CALL toi(wchar_t c
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      return re_toi(c MAYBE_PASS_LOCALE(l));
   }
   static int RE_CALL toi(const wchar_t*& first, const wchar_t* last, int radix
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      return re_toi(first, last, radix MAYBE_PASS_LOCALE(l));
   }

   static jm_uintfast32_t RE_CALL lookup_classname(const wchar_t* first, const wchar_t* last
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      return JM_USE_FACET(l, regfacet<wchar_t>).lookup_classname(first, last);
      #else
      return re_lookup_class(first, last);
      #endif
   }


   static bool RE_CALL lookup_collatename(re_str<wchar_t>& s, const wchar_t* first, const wchar_t* last
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      re_str<wchar_t> n(first, last);
      return JM_USE_FACET(l, regfacet<wchar_t>).lookup_collatename(s, n);
      #else
      return re_lookup_collate(s, first, last);
      #endif
   }
};
#endif

//
// class char_regex_traits_i
// provides case insensitive traits classes:
template <class charT>
class char_regex_traits_i : public char_regex_traits<charT> {};

JM_TEMPLATE_SPECIALISE
class char_regex_traits_i<char> : public char_regex_traits<char>
{
public:
   typedef char char_type;
   typedef unsigned char uchar_type;
   typedef unsigned int size_type;
   typedef char_regex_traits<char> base_type;

   static char RE_CALL translate(char c, bool
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      return JM_USE_FACET(l, __JM_STD::ctype<char>).tolower((char_type)c);
      #else
      return re_lower_case_map[(size_type)(uchar_type)c];
      #endif
   }
};

#ifndef JM_NO_WCSTRING
JM_TEMPLATE_SPECIALISE
class char_regex_traits_i<wchar_t> : public char_regex_traits<wchar_t>
{
public:
   typedef wchar_t char_type;
   typedef unsigned short uchar_type;
   typedef unsigned int size_type;
   typedef char_regex_traits<wchar_t> base_type;

   static wchar_t RE_CALL translate(wchar_t c, bool
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      #ifdef RE_LOCALE_CPP
      return JM_USE_FACET(l, __JM_STD::ctype<wchar_t>).tolower((char_type)c);
      #else
      return (c < 256) ? re_lower_case_map_w[(uchar_type)c] : re_wtolower(c);
      #endif
   }
   static jm_uintfast32_t RE_CALL lookup_classname(const wchar_t* first, const wchar_t* last
   #ifdef RE_LOCALE_CPP
   , const __JM_STD::locale& l
   #endif
   )
   {
      jm_uintfast32_t result = char_regex_traits<wchar_t>::lookup_classname(first, last MAYBE_PASS_LOCALE(l));
      if((result & char_class_upper) == char_class_upper)
         result |= char_class_alpha;
      return result;
   }
};
#endif

enum mask_type
{
   mask_take = 1,
   mask_skip = 2,
   mask_any = mask_skip | mask_take,
   mask_all = mask_any
};

struct __narrow_type{};
struct __wide_type{};

template <class charT>
class is_byte;

JM_TEMPLATE_SPECIALISE
class is_byte<char>
{
public:
   typedef __narrow_type width_type;
};

JM_TEMPLATE_SPECIALISE
class is_byte<unsigned char>
{
public:
   typedef __narrow_type width_type;
};

JM_TEMPLATE_SPECIALISE
class is_byte<signed char>
{
public:
   typedef __narrow_type width_type;
};

template <class charT>
class is_byte
{
public:
   typedef __wide_type width_type;
};


//
// compiled structures
//
// the following defs describe the format of the compiled string
//

//
// enum syntax_element_type
// describes the type of a record
enum syntax_element_type
{
   syntax_element_startmark = 0,
   syntax_element_endmark = syntax_element_startmark + 1,
   syntax_element_literal = syntax_element_endmark + 1,
   syntax_element_start_line = syntax_element_literal + 1,
   syntax_element_end_line = syntax_element_start_line + 1,
   syntax_element_wild = syntax_element_end_line + 1,
   syntax_element_match = syntax_element_wild + 1,
   syntax_element_word_boundary = syntax_element_match + 1,
   syntax_element_within_word = syntax_element_word_boundary + 1,
   syntax_element_word_start = syntax_element_within_word + 1,
   syntax_element_word_end = syntax_element_word_start + 1,
   syntax_element_buffer_start = syntax_element_word_end + 1,
   syntax_element_buffer_end = syntax_element_buffer_start + 1,
   syntax_element_backref = syntax_element_buffer_end + 1,
   syntax_element_long_set = syntax_element_backref + 1,
   syntax_element_set = syntax_element_long_set + 1,
   syntax_element_jump = syntax_element_set + 1,
   syntax_element_alt = syntax_element_jump + 1,
   syntax_element_rep = syntax_element_alt + 1,
   syntax_element_combining = syntax_element_rep + 1,
   syntax_element_soft_buffer_end = syntax_element_combining + 1,
   syntax_element_restart_continue = syntax_element_soft_buffer_end + 1
};

union offset_type
{
   re_syntax_base* p;
   unsigned i;
};

//
// struct re_syntax_base
// base class for all syntax types:
struct re_syntax_base
{
   syntax_element_type type;
   offset_type next;
   unsigned int can_be_null;
};

//
// struct re_brace
// marks start or end of (...)
struct re_brace : public re_syntax_base
{
   unsigned int index;
};

//
// struct re_literal
// marks a literal string and
// is followed by an array of charT[length]:
struct re_literal : public re_syntax_base
{
   unsigned int length;
};

//
// struct re_long_set
// provides data for sets [...] containing
// wide characters
struct re_set_long : public re_syntax_base
{
   unsigned int csingles, cranges, cequivalents;
   jm_uintfast32_t cclasses;
   bool isnot;
};

//
// struct re_set
// provides a map of bools for sets containing
// narrow, single byte characters.
struct re_set : public re_syntax_base
{
   unsigned char __map[256];
};

//
// struct re_jump
// provides alternative next destination
struct re_jump : public re_syntax_base
{
   offset_type alt;
   unsigned char __map[256];
};

//
// struct re_repeat
// provides repeat expressions
struct re_repeat : public re_jump
{
   unsigned min, max;
   int id;
   bool leading;
};


//
// enum re_jump_size_type
// provides compiled size of re_jump
// allowing for trailing alignment
// provide this so we know how many
// bytes to insert
enum re_jump_size_type
{
   re_jump_size = (sizeof(re_jump) + sizeof(padding) - 1) & ~(sizeof(padding) - 1),
   re_repeater_size = (sizeof(re_repeat) + sizeof(padding) - 1) & ~(sizeof(padding) - 1)
};


//
// class basic_regex
// handles error codes and flags

class JM_IX_DECL regbase
{
protected:
#ifdef RE_LOCALE_CPP
   __JM_STD::locale locale_inst;
#endif
   jm_uintfast32_t _flags;
   unsigned int code;
public:
   enum flag_type
   {
      escape_in_lists = 1,                     // '\' special inside [...]
      char_classes = escape_in_lists << 1,     // [[:CLASS:]] allowed
      intervals = char_classes << 1,           // {x,y} allowed
      limited_ops = intervals << 1,            // all of + ? and | are normal characters
      newline_alt = limited_ops << 1,          // \n is the same as |
      bk_plus_qm = newline_alt << 1,           // uses \+ and \?
      bk_braces = bk_plus_qm << 1,             // uses \{ and \}
      bk_parens = bk_braces << 1,              // uses \( and \)
      bk_refs = bk_parens << 1,                // \d allowed
      bk_vbar = bk_refs << 1,                  // uses \|
      use_except = bk_vbar << 1,               // exception on error
      failbit = use_except << 1,               // error flag
      literal = failbit << 1,                  // all characters are literals
      icase = literal << 1,                    // characters are matched regardless of case
      nocollate = icase << 1,                  // don't use locale specific collation

      basic = char_classes | intervals | limited_ops | bk_braces | bk_parens | bk_refs,
      extended = char_classes | intervals | bk_refs,
      normal = escape_in_lists | char_classes | intervals | bk_refs | nocollate
   };

   enum restart_info
   {
      restart_any = 0,
      restart_word = 1,
      restart_line = 2,
      restart_buf = 3,
      restart_continue = 4,
      restart_lit = 5,
      restart_fixed_lit = 6
   };

   unsigned int RE_CALL error_code()const
   {
      return code;
   }

   void RE_CALL fail(unsigned int err);

   jm_uintfast32_t RE_CALL flags()const
   {
      return _flags;
   }
#ifdef RE_LOCALE_CPP
   __JM_STD::string RE_CALL errmsg()const
   {
      return re_get_error_str(code, locale_inst);
   }
#else
   const char* RE_CALL errmsg()const
   {
      return re_get_error_str(code);
   }
#endif

   regbase();
   regbase(const regbase& b);

   #ifdef RE_LOCALE_CPP
   __JM_STD::locale RE_CALL imbue(const __JM_STD::locale& l);
   
   const __JM_STD::locale& RE_CALL locale()const
   {
      return locale_inst;
   }
   #endif
};

//
// some forward declarations:

template <class iterator, class Allocator JM_DEF_ALLOC_PARAM(iterator) >
class reg_match;

template <class iterator, class Allocator>
class __priv_match_data;


//
// class reg_expression
// represents the compiled
// regular expression:
//

#if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES)
//
// Ugly ugly hack,
// template don't merge if they contain switch statements so declare these
// templates in unnamed namespace (ie with internal linkage), each translation
// unit then gets its own local copy, it works seemlessly but bloats the app.
namespace{
#endif

template <class charT, class traits JM_TRICKY_DEFAULT_PARAM(char_regex_traits<charT>), class Allocator JM_DEF_ALLOC_PARAM(charT) >
class reg_expression : public regbase
{
public:
   // typedefs:
   typedef Allocator alloc_type;
   typedef typename REBIND_TYPE(charT, alloc_type)::size_type size_type;
   typedef charT value_type;
   typedef charT char_type;
   typedef traits traits_type;
   typedef typename traits_type::size_type traits_size_type;
   typedef typename traits_type::uchar_type traits_uchar_type;

private:
#if defined(RE_LOCALE_C) || defined(RE_LOCALE_W32)
   re_initialiser<charT> locale_initialiser;
#endif
   raw_storage<Allocator> data;
   unsigned _restart_type;
   unsigned marks;
   int repeats;
   unsigned char* startmap;
   charT* _expression;
   unsigned int _leading_len;
   const charT* _leading_string;
   unsigned int _leading_string_len;
   kmp_info<charT>* pkmp;

   void RE_CALL compile_maps();
   void RE_CALL compile_map(re_syntax_base* node, unsigned char* __map, unsigned int* pnull, unsigned char mask, re_syntax_base* terminal = NULL)const;
   bool RE_CALL probe_start(re_syntax_base* node, charT c, re_syntax_base* terminal)const;
   bool RE_CALL probe_start_null(re_syntax_base* node, re_syntax_base* terminal)const;
   void RE_CALL fixup_apply(re_syntax_base* b, unsigned cbraces);
   void RE_CALL move_offsets(re_syntax_base* j, unsigned size);
   re_syntax_base* RE_CALL compile_set(const charT*& first, const charT* last);
   re_syntax_base* RE_CALL compile_set_aux(jstack<re_str<charT>, Allocator>& singles, jstack<re_str<charT>, Allocator>& ranges, jstack<jm_uintfast32_t, Allocator>& classes, jstack<re_str<charT>, Allocator>& equivalents, bool isnot, const __narrow_type&);
   re_syntax_base* RE_CALL compile_set_aux(jstack<re_str<charT>, Allocator>& singles, jstack<re_str<charT>, Allocator>& ranges, jstack<jm_uintfast32_t, Allocator>& classes, jstack<re_str<charT>, Allocator>& equivalents, bool isnot, const __wide_type&);
   re_syntax_base* RE_CALL compile_set_simple(re_syntax_base* dat, unsigned long cls, bool isnot = false);
   unsigned int RE_CALL parse_inner_set(const charT*& first, const charT* last);

   re_syntax_base* RE_CALL add_simple(re_syntax_base* dat, syntax_element_type type, unsigned int size = sizeof(re_syntax_base));
   re_syntax_base* RE_CALL add_literal(re_syntax_base* dat, charT c);
   charT RE_CALL parse_escape(const charT*& first, const charT* last);
   void RE_CALL parse_range(const charT*& first, const charT* last, unsigned& min, unsigned& max);
   bool RE_CALL skip_space(const charT*& first, const charT* last);
   unsigned int RE_CALL probe_restart(re_syntax_base* dat);
   unsigned int RE_CALL fixup_leading_rep(re_syntax_base* dat, re_syntax_base* end);

public:
   unsigned int RE_CALL set_expression(const charT* p, const charT* end, jm_uintfast32_t f = regbase::normal);
   unsigned int RE_CALL set_expression(const charT* p, jm_uintfast32_t f = regbase::normal) { return set_expression(p, p + traits_type::length(p), f); }
   reg_expression(const Allocator& a = Allocator());
   reg_expression(const charT* p, jm_uintfast32_t f = regbase::normal, const Allocator& a = Allocator());
   reg_expression(const charT* p1, const charT* p2, jm_uintfast32_t f = regbase::normal, const Allocator& a = Allocator());
   reg_expression(const charT* p, size_type len, jm_uintfast32_t f, const Allocator& a = Allocator());
   reg_expression(const reg_expression&);
   ~reg_expression();
   reg_expression& RE_CALL operator=(const reg_expression&);

#ifndef JM_NO_MEMBER_TEMPLATES

   template <class ST, class SA>
   unsigned int RE_CALL set_expression(const __JM_STD::basic_string<charT, ST, SA>& p, jm_uintfast32_t f = regbase::normal) 
   { return set_expression(p.data(), p.data() + p.size(), f); }

   template <class ST, class SA>
   reg_expression(const __JM_STD::basic_string<charT, ST, SA>& p, jm_uintfast32_t f = regbase::normal, const Allocator& a = Allocator())
    : data(a), pkmp(0) { set_expression(p, f); }

#elif !defined(JM_NO_STRING_DEF_ARGS)
   unsigned int RE_CALL set_expression(const __JM_STD::basic_string<charT>& p, jm_uintfast32_t f = regbase::normal) 
   { return set_expression(p.data(), p.data() + p.size(), f); }

   reg_expression(const __JM_STD::basic_string<charT>& p, jm_uintfast32_t f = regbase::normal, const Allocator& a = Allocator())
    : data(a), pkmp(0) { set_expression(p, f); }
   
#endif


   bool RE_CALL operator==(const reg_expression&);
   bool RE_CALL operator<(const reg_expression&);
   alloc_type RE_CALL allocator()const;
   const charT* RE_CALL expression()const { return _expression; }
   unsigned RE_CALL mark_count()const { return marks; }

#if !defined(JM_NO_TEMPLATE_FRIEND) && (!defined(JM_NO_TEMPLATE_SWITCH_MERGE) || defined(JM_NO_NAMESPACES))
#if 0
   template <class Predicate, class I, class charT, class traits, class A, class A2>
   friend unsigned int reg_grep2(Predicate foo, I first, I last, const reg_expression<charT, traits, A>& e, unsigned flags, A2 a);
   
   template <class I, class A, class charT, class traits, class A2>
   friend bool query_match(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e, unsigned flags);

   template <class I, class A, class charT, class traits, class A2>
   friend bool query_match_aux(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e, 
                        unsigned flags, __priv_match_data<I, A>& pd, I* restart);

   template <class I, class A, class charT, class traits, class A2>
   friend bool reg_search(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e, unsigned flags);
private:
#endif
#endif

   int RE_CALL repeat_count() const { return repeats; }
   unsigned int RE_CALL restart_type()const { return _restart_type; }
   const re_syntax_base* RE_CALL first()const { return (const re_syntax_base*)data.data(); }
   const unsigned char* RE_CALL get_map()const { return startmap; }
   unsigned int RE_CALL leading_length()const { return _leading_len; }
   const kmp_info<charT>* get_kmp()const { return pkmp; }
   static bool RE_CALL can_start(charT c, const unsigned char* __map, unsigned char mask, const __wide_type&);
   static bool RE_CALL can_start(charT c, const unsigned char* __map, unsigned char mask, const __narrow_type&);
};

#if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES)
} // namespace
#endif


//
// class reg_match and reg_match_base
// handles what matched where

template <class iterator>
struct sub_match
{
   iterator first;
   iterator second;
   bool matched;
#ifndef JM_NO_MEMBER_TEMPLATES
   template <class charT, class traits, class Allocator>
   operator __JM_STD::basic_string<charT, traits, Allocator> ()const;
#elif !defined(JM_NO_STRING_DEF_ARGS)
   operator __JM_STD::basic_string<char> ()const;
   operator __JM_STD::basic_string<wchar_t> ()const;
#endif
   operator int()const;
   operator unsigned int()const;
   operator short()const
   {
      return (short)(int)(*this);
   }
   operator unsigned short()const
   {
      return (unsigned short)(unsigned int)(*this);
   }
   sub_match() { matched = false; }
   sub_match(iterator i) : first(i), second(i), matched(false) {}
};

#ifndef JM_NO_MEMBER_TEMPLATES
template <class iterator>
template <class charT, class traits, class Allocator>
sub_match<iterator>::operator __JM_STD::basic_string<charT, traits, Allocator> ()const
{
#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_TYPEINFO)
   if(typeid(charT) != typeid(*first))
      throw __JM_STD::bad_cast();
#endif
   __JM_STD::basic_string<charT, traits, Allocator> result;
   iterator i = first;
   while(i != second)
   {
      result.append(1, *i);
      ++i;
   }
   return result;
}
#elif !defined(JM_NO_STRING_DEF_ARGS)
template <class iterator>
sub_match<iterator>::operator __JM_STD::basic_string<char> ()const
{
#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_TYPEINFO)
   if(typeid(char) != typeid(*first))
      throw __JM_STD::bad_cast();
#endif
   __JM_STD::basic_string<char> result;
   iterator i = first;
   while(i != second)
   {
      result.append(1, *i);
      ++i;
   }
   return result;
}
template <class iterator>
sub_match<iterator>::operator __JM_STD::basic_string<wchar_t> ()const
{
#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_TYPEINFO)
   if(typeid(wchar_t) != typeid(*first))
      throw __JM_STD::bad_cast();
#endif
   __JM_STD::basic_string<wchar_t> result;
   iterator i = first;
   while(i != second)
   {
      result.append(1, *i);
      ++i;
   }
   return result;
}
#endif
template <class iterator>
sub_match<iterator>::operator int()const
{
   iterator i = first;
   int neg = 1;
   if((i != second) && (*i == '-'))
   {
      neg = -1;
      ++i;
   }
   neg *= (int)re_toi(i, second, 10 MAYBE_PASS_LOCALE(__JM_STD::locale()));
#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_TYPEINFO)
   if(i != second)
   {
      throw __JM_STD::bad_cast();
   }
#endif
   return neg;
}
template <class iterator>
sub_match<iterator>::operator unsigned int()const
{
   iterator i = first;
   unsigned int result = (int)re_toi(i, second, 10 MAYBE_PASS_LOCALE(__JM_STD::locale()));
#if !defined(JM_NO_EXCEPTIONS) && !defined(JM_NO_TYPEINFO)
   if(i != second)
   {
      throw __JM_STD::bad_cast();
   }
#endif
   return result;
}


template <class iterator, class Allocator JM_DEF_ALLOC_PARAM(iterator) >
class reg_match_base
{
public:
   typedef Allocator alloc_type;
   typedef typename REBIND_TYPE(iterator, Allocator)::size_type size_type;
   typedef JM_MAYBE_TYPENAME REBIND_TYPE(char, Allocator) c_alloc;
   typedef iterator value_type;

protected:
   struct reference : public c_alloc
   {
      unsigned int cmatches;
      unsigned count;
      sub_match<iterator> head, tail, null;
      unsigned int lines;
      iterator line_pos;
      reference(const Allocator& a) : c_alloc(a) {  }
   };

   reference* ref;

   void RE_CALL cow();

   // protected contructor for derived class...
   reg_match_base(bool){}
   void RE_CALL free();

public:

   reg_match_base(const Allocator& a = Allocator());

   reg_match_base(const reg_match_base& m)
   {
      ref = m.ref;
      ++(ref->count);
   }

   reg_match_base& RE_CALL operator=(const reg_match_base& m);

   ~reg_match_base()
   {
      free();
   }

   size_type RE_CALL size()const
   {
      return ref->cmatches;
   }

   const sub_match<iterator>& RE_CALL operator[](int n) const
   {
      if((n >= 0) && ((unsigned int)n < ref->cmatches))
         return *(sub_match<iterator>*)((char*)ref + sizeof(reference) + sizeof(sub_match<iterator>)*n);
      return (n == -1) ? ref->head : (n == -2) ? ref->tail : ref->null;
   }

   Allocator RE_CALL allocator()const;

   size_t RE_CALL length()const
   {
      jm_assert(ref->cmatches);
      size_t n = 0;
      JM_DISTANCE(((sub_match<iterator>*)(ref+1))->first, ((sub_match<iterator>*)(ref+1))->second, n);
      return n;
   }

   unsigned int RE_CALL line()const
   {
      return ref->lines;
   }

   iterator RE_CALL line_start()const
   {
      return ref->line_pos;
   }

   void swap(reg_match_base& that)
   {
      reference* t = that.ref;
      that.ref = ref;
      ref = t;
   }

   friend class reg_match<iterator, Allocator>;
#if !defined(JM_NO_TEMPLATE_FRIEND) && (!defined(JM_NO_TEMPLATE_SWITCH_MERGE) || defined(JM_NO_NAMESPACES))
private:
   template <class Predicate, class I, class charT, class traits, class A, class A2>
   friend unsigned int reg_grep2(Predicate foo, I first, I last, const reg_expression<charT, traits, A>& e, unsigned flags, A2 a);
   
   template <class I, class A, class charT, class traits, class A2>
   friend bool query_match(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e, unsigned flags);

   template <class I, class A, class charT, class traits, class A2>
   friend bool query_match_aux(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e, 
                        unsigned flags, __priv_match_data<I, A>& pd, I* restart);

   template <class I, class A, class charT, class traits, class A2>
   friend bool reg_search(I first, I last, reg_match<I, A>& m, const reg_expression<charT, traits, A2>& e, unsigned flags);
#endif
   void RE_CALL set_size(size_type n);
   void RE_CALL set_size(size_type n, iterator i, iterator j);
   void RE_CALL maybe_assign(const reg_match_base& m);
   void RE_CALL init_fail(iterator i, iterator j);

   void RE_CALL set_first(iterator i)
   {
      cow();
      ((sub_match<iterator>*)(ref+1))->first = i;
      ref->head.second = i;
      ref->head.matched = (ref->head.first == ref->head.second) ? false : true;
   }

   void RE_CALL set_first(iterator i, size_t pos)
   {
      cow();
      ((sub_match<iterator>*)((char*)ref + sizeof(reference) + sizeof(sub_match<iterator>) * pos))->first = i;
      if(pos == 0)
      {
         ref->head.second = i;
         ref->head.matched = (ref->head.first == ref->head.second) ? false : true;
      }
   }

   void RE_CALL set_second(iterator i)
   {
      cow();
      ((sub_match<iterator>*)(ref+1))->second = i;
      ((sub_match<iterator>*)(ref+1))->matched = true;
      ref->tail.first = i;
      ref->tail.matched = (ref->tail.first == ref->tail.second) ? false : true;
   }

   void RE_CALL set_second(iterator i, size_t pos)
   {
      cow();
      ((sub_match<iterator>*)((char*)ref + sizeof(reference) + sizeof(sub_match<iterator>) * pos))->second = i;
      ((sub_match<iterator>*)((char*)ref + sizeof(reference) + sizeof(sub_match<iterator>) * pos))->matched = true;
      if(pos == 0)
      {
         ref->tail.first = i;
         ref->tail.matched = (ref->tail.first == ref->tail.second) ? false : true;
      }
   }

   void RE_CALL set_line(unsigned int i, iterator pos)
   {
      ref->lines = i;
      ref->line_pos = pos;
   }
};

template <class iterator, class Allocator>
reg_match_base<iterator, Allocator>::reg_match_base(const Allocator& a)
{
   ref = (reference*)c_alloc(a).allocate(sizeof(sub_match<iterator>) + sizeof(reference));
#ifndef JM_NO_EXCEPTIONS
   try
   {
#endif
      new (ref) reference(a);
      ref->cmatches = 1;
      ref->count = 1;
      // construct the sub_match<iterator>:
#ifndef JM_NO_EXCEPTIONS
      try
      {
#endif
         new ((sub_match<iterator>*)(ref+1)) sub_match<iterator>();
#ifndef JM_NO_EXCEPTIONS
      }
      catch(...)
      { 
         jm_destroy(ref); 
         throw; 
      }
#endif
#ifndef JM_NO_EXCEPTIONS
   }
   catch(...)
   { 
      c_alloc(a).deallocate((char*)(void*)ref, sizeof(sub_match<iterator>) + sizeof(reference)); 
      throw; 
   }
#endif
}

template <class iterator, class Allocator>
Allocator RE_CALL reg_match_base<iterator, Allocator>::allocator()const
{
  return *((c_alloc*)ref);
}

template <class iterator, class Allocator>
inline reg_match_base<iterator, Allocator>& RE_CALL reg_match_base<iterator, Allocator>::operator=(const reg_match_base<iterator, Allocator>& m)
{
   if(ref != m.ref)
   {
      free();
      ref = m.ref;
      ++(ref->count);
   }
   return *this;
}


template <class iterator, class Allocator>
void RE_CALL reg_match_base<iterator, Allocator>::free()
{
   if(--(ref->count) == 0)
   {
      c_alloc a(*ref);
      sub_match<iterator>* p1, *p2;
      p1 = (sub_match<iterator>*)(ref+1);
      p2 = p1 + ref->cmatches;
      while(p1 != p2)
      {
         jm_destroy(p1);
         ++p1;
      }
      jm_destroy(ref);
      a.deallocate((char*)(void*)ref, sizeof(sub_match<iterator>) * ref->cmatches + sizeof(reference));
   }
}

template <class iterator, class Allocator>
void RE_CALL reg_match_base<iterator, Allocator>::set_size(size_type n)
{
   if(ref->cmatches != n)
   {
      reference* newref = (reference*)ref->allocate(sizeof(sub_match<iterator>) * n + sizeof(reference));
#ifndef JM_NO_EXCEPTIONS
      try
      {
#endif
         new (newref) reference(*ref);
         newref->count = 1;
         newref->cmatches = n;
         sub_match<iterator>* p1, *p2;
         p1 = (sub_match<iterator>*)(newref+1);
         p2 = p1 + newref->cmatches;
#ifndef JM_NO_EXCEPTIONS
         try
         {
#endif
            while(p1 != p2)
            {
               new (p1) sub_match<iterator>();
               ++p1;
            }
            free();
#ifndef JM_NO_EXCEPTIONS
         }
         catch(...)
         { 
            p2 = (sub_match<iterator>*)(newref+1);
            while(p2 != p1)
            {
               jm_destroy(p2);
               ++p2;
            }
            jm_destroy(ref);
            throw; 
         }
#endif
         ref = newref;
#ifndef JM_NO_EXCEPTIONS
      }
      catch(...)
      { 
         ref->deallocate((char*)(void*)newref, sizeof(sub_match<iterator>) * n + sizeof(reference)); 
         throw; 
      }
#endif
   }
}

template <class iterator, class Allocator>
void RE_CALL reg_match_base<iterator, Allocator>::set_size(size_type n, iterator i, iterator j)
{
   if(ref->cmatches != n)
   {
      reference* newref = (reference*)ref->allocate(sizeof(sub_match<iterator>) * n + sizeof(reference));;
#ifndef JM_NO_EXCEPTIONS
      try{
#endif
         new (newref) reference(*ref);
         newref->count = 1;
         newref->cmatches = n;
         sub_match<iterator>* p1, *p2;
         p1 = (sub_match<iterator>*)(newref+1);
         p2 = p1 + newref->cmatches;
#ifndef JM_NO_EXCEPTIONS
         try
         {
#endif
            while(p1 != p2)
            {
               new (p1) sub_match<iterator>(j);
               ++p1;
            }
            free();
#ifndef JM_NO_EXCEPTIONS
         }
         catch(...)
         { 
            p2 = (sub_match<iterator>*)(newref+1);
            while(p2 != p1)
            {
               jm_destroy(p2);
               ++p2;
            }
            jm_destroy(ref);
            throw; 
         }
#endif
         ref = newref;
#ifndef JM_NO_EXCEPTIONS
      }
      catch(...)
      { 
         ref->deallocate((char*)(void*)newref, sizeof(sub_match<iterator>) * n + sizeof(reference)); 
         throw; 
      }
#endif
   }
   else
   {
      cow();
      // set iterators to be i, matched to false:
      sub_match<iterator>* p1, *p2;
      p1 = (sub_match<iterator>*)(ref+1);
      p2 = p1 + ref->cmatches;
      while(p1 != p2)
      {
         p1->first = j;
         p1->second = j;
         p1->matched = false;
         ++p1;
      }
   }
   ref->head.first = i;
   ref->tail.second = j;
   ref->head.matched = ref->tail.matched = true;
   ref->null.first = ref->null.second = j;
   ref->null.matched = false;
}

template <class iterator, class Allocator>
inline void RE_CALL reg_match_base<iterator, Allocator>::init_fail(iterator i, iterator j)
{
   set_size(ref->cmatches, i, j);
}

template <class iterator, class Allocator>
void RE_CALL reg_match_base<iterator, Allocator>::maybe_assign(const reg_match_base<iterator, Allocator>& m)
{
   sub_match<iterator>* p1, *p2;
   p1 = (sub_match<iterator>*)(ref+1);
   p2 = (sub_match<iterator>*)(m.ref+1);
   unsigned int len1, len2;
   unsigned int i;
   for(i = 0; i < ref->cmatches; ++i)
   {
      len1 = len2 = 0;
      JM_DISTANCE(p1->first, p1->second, len1);
      JM_DISTANCE(p2->first, p2->second, len2);
      if((len1 != len2) || ((p1->matched == false) && (p2->matched == true)))
         break;
      if((p1->matched == true) && (p2->matched == false))
         return;
      ++p1;
      ++p2;
   }
   if(i == ref->cmatches)
      return;
   if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) )
      *this = m;
}

template <class iterator, class Allocator>
void RE_CALL reg_match_base<iterator, Allocator>::cow()
{
   if(ref->count > 1)
   {
      reference* newref = (reference*)ref->allocate(sizeof(sub_match<iterator>) * ref->cmatches + sizeof(reference));
#ifndef JM_NO_EXCEPTIONS
      try{
#endif
         new (newref) reference(*ref);
         newref->count = 1;
         sub_match<iterator>* p1, *p2, *p3;
         p1 = (sub_match<iterator>*)(newref+1);
         p2 = p1 + newref->cmatches;
         p3 = (sub_match<iterator>*)(ref+1);
#ifndef JM_NO_EXCEPTIONS
         try{
#endif
            while(p1 != p2)
            {
               new (p1) sub_match<iterator>(*p3);
               ++p1;
               ++p3;
            }
#ifndef JM_NO_EXCEPTIONS
         }
         catch(...)
         { 
            p2 = (sub_match<iterator>*)(newref+1);
            while(p2 != p1)
            {
               jm_destroy(p2);
               ++p2;
            }
            jm_destroy(ref);
            throw; 
         }
#endif
      --(ref->count);
      ref = newref;
#ifndef JM_NO_EXCEPTIONS
      }
      catch(...)
      { 
         ref->deallocate((char*)(void*)newref, sizeof(sub_match<iterator>) * ref->cmatches + sizeof(reference)); 
         throw; 
      }
#endif
   }
}

//
// class reg_match
// encapsulates reg_match_base, does a deep copy rather than
// reference counting to ensure thread safety when copying
// other reg_match instances

template <class iterator, class Allocator>
class reg_match : public reg_match_base<iterator, Allocator>
{
public:
   reg_match(const Allocator& a = Allocator())
      : reg_match_base<iterator, Allocator>(a){}

   reg_match(const reg_match_base<iterator, Allocator>& m)
      : reg_match_base<iterator, Allocator>(m){}

   reg_match& operator=(const reg_match_base<iterator, Allocator>& m)
   {
      // shallow copy
      reg_match_base<iterator, Allocator>::operator=(m);
      return *this;
   }

   reg_match(const reg_match& m);
   reg_match& operator=(const reg_match& m);

};

template <class iterator, class Allocator>
reg_match<iterator, Allocator>::reg_match(const reg_match<iterator, Allocator>& m)
   : reg_match_base<iterator, Allocator>(false)
{
   reg_match_base<iterator, Allocator>::ref = (typename reg_match_base<iterator, Allocator>::reference *)m.ref->allocate(sizeof(sub_match<iterator>) * m.ref->cmatches + sizeof(typename reg_match_base<iterator, Allocator>::reference));
#ifndef JM_NO_EXCEPTIONS
   try{
#endif
      new (reg_match_base<iterator, Allocator>::ref) typename reg_match_base<iterator, Allocator>::reference(*m.ref);
      reg_match_base<iterator, Allocator>::ref->count = 1;
      sub_match<iterator>* p1, *p2, *p3;
      p1 = (sub_match<iterator>*)(reg_match_base<iterator, Allocator>::ref+1);
      p2 = p1 + reg_match_base<iterator, Allocator>::ref->cmatches;
      p3 = (sub_match<iterator>*)(m.ref+1);
#ifndef JM_NO_EXCEPTIONS
      try{
#endif
         while(p1 != p2)
         {
            new (p1) sub_match<iterator>(*p3);
            ++p1;
            ++p3;
         }
#ifndef JM_NO_EXCEPTIONS
      }
      catch(...)
      { 
         p2 = (sub_match<iterator>*)(reg_match_base<iterator, Allocator>::ref+1);
         while(p2 != p1)
         {
            jm_destroy(p2);
            ++p2;
         }
         jm_destroy(ref);
         throw; 
      }
   }
   catch(...)
   { 
      m.ref->deallocate((char*)(void*)reg_match_base<iterator, Allocator>::ref, sizeof(sub_match<iterator>) * m.ref->cmatches + sizeof(typename reg_match_base<iterator, Allocator>::reference)); 
      throw; 
   }
#endif
}

template <class iterator, class Allocator>
reg_match<iterator, Allocator>& reg_match<iterator, Allocator>::operator=(const reg_match<iterator, Allocator>& m)
{
   reg_match<iterator, Allocator> t(m);
   this->swap(t);
   return *this;
}


template <class iterator, class charT, class traits_type, class Allocator>
iterator RE_CALL re_is_set_member(iterator next, 
                          iterator last, 
                          re_set_long* set, 
                          const reg_expression<charT, traits_type, Allocator>& e);

JM_END_NAMESPACE   // namespace regex

#include <jm/regcomp.h>

JM_NAMESPACE(__JM)

typedef reg_expression<char, char_regex_traits<char>, JM_DEF_ALLOC(char)> regex;
#ifndef JM_NO_WCSTRING
typedef reg_expression<wchar_t, char_regex_traits<wchar_t>, JM_DEF_ALLOC(wchar_t)> wregex;
#endif

typedef reg_match<const char*, regex::alloc_type> cmatch;
#ifndef JM_NO_WCSTRING
typedef reg_match<const wchar_t*, wregex::alloc_type> wcmatch;
#endif

JM_END_NAMESPACE   // namespace regex

#include <jm/regmatch.h>
#include <jm/regfmt.h>

#if !defined(JM_NO_NAMESPACES) && !defined(JM_NO_USING)

#ifndef JM_NO_EXCEPTIONS
using __JM::bad_expression;
#endif
using __JM::char_regex_traits;
using __JM::char_regex_traits_i;
using __JM::regbase;
using __JM::reg_expression;
using __JM::reg_match;
using __JM::reg_match_base;
using __JM::sub_match;
using __JM::regex;
using __JM::cmatch;
#ifndef JM_NO_WCSTRING
using __JM::wregex;
using __JM::wcmatch;
#endif
using __JM::query_match;
using __JM::reg_search;
using __JM::reg_grep;
using __JM::reg_format;
using __JM::reg_merge;
using __JM::jm_def_alloc;

#endif

#endif  // __cplusplus

#endif  // include















