/* \file macros.h
 * \brief: global macros used in the whole code
 */

/*Header {{{*/
#ifndef _MACROS_H_
#define _MACROS_H_

#include <iostream>
#include <sstream>
#include <iomanip>
#include "./typedefs.h"

#ifdef HAVE_CONFIG_H
	#include <config.h>
#else
#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
#endif
/*}}}*/

/* _printf_ {{{*/
/*Printing macro: only cpu number 0 */
#define _printf_(flag,...) do{if(flag) PrintfFunction(__VA_ARGS__);}while(0)
/*}}}*/
/* _error_ {{{*/
/*Error exception macro*/
#ifdef _INTEL_WIN_
#define _error_(...)\
  throw ErrorException(exprintf(__VA_ARGS__))
#else
#define _error_(...)\
  throw ErrorException(__FILE__,__func__,__LINE__,exprintf(__VA_ARGS__))
#endif
/*}}}*/
/* _error2_ {{{*/
/*new Error exception macro*/
#ifdef _INTEL_WIN_
#define _error2_(StreamArgs)\
   do{std::ostringstream aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy; \
   aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy << StreamArgs << std::ends; \
   throw ErrorException(aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy.str());}while(0)
#else
#define _error2_(StreamArgs)\
	do{std::ostringstream aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy; \
   aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy << StreamArgs << std::ends; \
   throw ErrorException(__FILE__,__func__,__LINE__,aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy.str());}while(0)
#endif
/*}}}*/
/* _printLine_ {{{*/
/* macro to print a line, adds std::endl */
#define _printLine_(StreamArgs)\
   do{std::cout << StreamArgs << std::endl;}while(0)
/*}}}*/
/* _printString_ {{{*/
/* macro to print some string, adds std::ends */
#define _printString_(StreamArgs)\
   do{std::cout << StreamArgs;}while(0)
/*}}}*/
/* _pprintLine_ {{{*/
/* macro to print a line, adds std::endl */
#define _pprintLine_(StreamArgs)\
  do{std::ostringstream aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy; \
	  aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy << StreamArgs << std::ends; \
	  PrintfFunction(aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy.str());}while(0)
/*}}}*/
/* _pprintString_ {{{*/
/* macro to print some string, adds std::ends */
#define _pprintString_(StreamArgs)\
  do{std::ostringstream aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy; \
	  aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy << StreamArgs << std::ends; \
	  PrintfFunction2(aLoNgAnDwEiRdLoCaLnAmeFoRtHiSmAcRoOnLy.str());}while(0)
/*}}}*/
/* _assert_ {{{*/
/*Assertion macro: do nothing if macro _ISSM_DEBUG_ undefined*/
#ifdef _ISSM_DEBUG_ 
#define _assert_(statement)\
  if (!(statement)) _error_("Assertion \"%s\" failed, please report bug to %s",#statement,PACKAGE_BUGREPORT)
#else
#define _assert_(ignore)\
  ((void) 0)
#endif
/*}}}*/
/* ISSMBOOT/ISSMEND {{{*/

/*The following macros hide the error exception handling in a matlab module. Just put 
 * ISSMBOOT(); and ISSMEND(); at the beginning and end of a module, and c++ exceptions 
 * will be trapped. Really nifty!*/

#define ISSMBOOT(); \
	try{

#define ISSMEND(); }\
	catch(ErrorException &exception){\
		exception.Report(); \
		return 1;\
	}\
	catch (exception& e) {\
		_printf_(true,"Standard exception: %s\n",e.what());\
		return 1;\
	}\
	catch(...){\
		_printf_(true,"An unexpected error occurred");\
	}
/*}}}*/

#endif
