/*

 *

 * Copyright (c) 1998-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.cpp

  *   VERSION:     see <boost/version.hpp>

  *   DESCRIPTION: Misc boost::regbase member funnctions.

  */





// Modification to prevent warning:AndyO

#ifndef BOOST_REGEX_SOURCE

#define BOOST_REGEX_SOURCE

#endif





#include <new>

#include <boost/regex.hpp>

#include <boost/throw_exception.hpp>



#if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && defined(_MSC_VER) && (_MSC_VER >= 1300)

#  include <malloc.h>

#endif

#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD

#define WIN32_LEAN_AND_MEAN

#ifndef NOMINMAX

#  define NOMINMAX

#endif

#define NOGDI

#define NOUSER

#include <windows.h>

#endif



#if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_REGEX_V3)

#if BOOST_REGEX_MAX_CACHE_BLOCKS == 0

#include <new>

#else

#include <boost/regex/v4/mem_block_cache.hpp>

#endif

#endif





namespace boost{



//

// fix: these are declared out of line here to ensure

// that dll builds contain the Virtual table for these

// types - this ensures that exceptions can be thrown

// from the dll and caught in an exe.

regex_error::regex_error(const std::string& s, regex_constants::error_type err, std::ptrdiff_t pos) 

   : std::runtime_error(s)

   , m_error_code(err)

   , m_position(pos) 

{

}



regex_error::regex_error(regex_constants::error_type err) 

   : std::runtime_error(::boost::re_detail::get_default_error_string(err))

   , m_error_code(err)

   , m_position(0) 

{

}



regex_error::~regex_error() throw() 

{

}



void regex_error::raise()const

{

#ifndef BOOST_NO_EXCEPTIONS

   ::boost::throw_exception(*this);

#endif

}







namespace re_detail{



BOOST_REGEX_DECL void BOOST_REGEX_CALL raise_runtime_error(const std::runtime_error& ex)

{

   ::boost::throw_exception(ex);

}

//

// error checking API:

//

BOOST_REGEX_DECL void BOOST_REGEX_CALL verify_options(boost::regex::flag_type /*ef*/, match_flag_type mf)

{

#ifndef BOOST_REGEX_V3

   //

   // can't mix match_extra with POSIX matching rules:

   //

   if((mf & match_extra) && (mf & match_posix))

   {

      std::logic_error msg("Usage Error: Can't mix regular expression captures with POSIX matching rules");

      throw_exception(msg);

   }

#endif

}



#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD



static void execute_eror()

{

   // we only get here after a stack overflow,

   // this has to be a separate proceedure because we 

   // can't mix __try{}__except block with local objects  

   // that have destructors:

   reset_stack_guard_page();

   std::runtime_error err("Out of stack space, while attempting to match a regular expression.");

   raise_runtime_error(err);

}



bool BOOST_REGEX_CALL abstract_protected_call::execute()const

{

   __try{

      return this->call();

   }__except(EXCEPTION_STACK_OVERFLOW == GetExceptionCode())

   {

      execute_eror();

   }

   // We never really get here at all:

   return false;

}



BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page()

{

#if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && defined(_MSC_VER) && (_MSC_VER >= 1300)

   _resetstkoflw();

#else

   //

   // We need to locate the current page being used by the stack,

   // move to the page below it and then deallocate and protect

   // that page.  Note that ideally we would protect only the lowest

   // stack page that has been allocated: in practice there

   // seems to be no easy way to locate this page, in any case as

   // long as the next page is protected, then Windows will figure

   // the rest out for us...

   //

   SYSTEM_INFO si;

   GetSystemInfo(&si);

   MEMORY_BASIC_INFORMATION mi;

   DWORD previous_protection_status;

   //

   // this is an address in our stack space:

   //

   LPBYTE page = (LPBYTE)&page;

   //

   // Get the current memory page in use:

   //

   VirtualQuery(page, &mi, sizeof(mi));

   //

   // Go to the page one below this:

   //

   page = (LPBYTE)(mi.BaseAddress)-si.dwPageSize;

   //

   // Free and protect everything from the start of the

   // allocation range, to the end of the page below the

   // one in use:

   //

   if (!VirtualFree(mi.AllocationBase, (LPBYTE)page - (LPBYTE)mi.AllocationBase, MEM_DECOMMIT)

      || !VirtualProtect(page, si.dwPageSize, PAGE_GUARD | PAGE_READWRITE, &previous_protection_status))

   {

      throw std::bad_exception();

   }

#endif

}

#endif



#if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_REGEX_V3)



#if BOOST_REGEX_MAX_CACHE_BLOCKS == 0



BOOST_REGEX_DECL void* BOOST_REGEX_CALL get_mem_block()

{

   return ::operator new(BOOST_REGEX_BLOCKSIZE);

}



BOOST_REGEX_DECL void BOOST_REGEX_CALL put_mem_block(void* p)

{

   ::operator delete(p);

}



#else



#ifdef BOOST_HAS_THREADS

mem_block_cache block_cache = { 0, 0, BOOST_STATIC_MUTEX_INIT, };

#else

mem_block_cache block_cache = { 0, 0, };

#endif



BOOST_REGEX_DECL void* BOOST_REGEX_CALL get_mem_block()

{

   return block_cache.get();

}



BOOST_REGEX_DECL void BOOST_REGEX_CALL put_mem_block(void* p)

{

   block_cache.put(p);

}



#endif



#endif



} // namespace re_detail







} // namespace boost



#if defined(BOOST_RE_USE_VCL) && defined(BOOST_REGEX_DYN_LINK)



int WINAPI DllEntryPoint(HINSTANCE , unsigned long , void*)

{

   return 1;

}

#endif



#if defined(__IBMCPP__) && defined(BOOST_REGEX_DYN_LINK)

//

// Is this correct - linker complains without it ?

//

int main()

{ 

   return 0; 

}



#endif













