1    	/****************************************************************************
2    	 *   Copyright (C) 2006-2008 by Jason Ansel                                 *
3    	 *   jansel@csail.mit.edu                                                   *
4    	 *                                                                          *
5    	 *   This file is part of the JALIB module of DMTCP (DMTCP:dmtcp/jalib).    *
6    	 *                                                                          *
7    	 *  DMTCP:dmtcp/jalib is free software: you can redistribute it and/or      *
8    	 *  modify it under the terms of the GNU Lesser General Public License as   *
9    	 *  published by the Free Software Foundation, either version 3 of the      *
10   	 *  License, or (at your option) any later version.                         *
11   	 *                                                                          *
12   	 *  DMTCP:dmtcp/src is distributed in the hope that it will be useful,      *
13   	 *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
14   	 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
15   	 *  GNU Lesser General Public License for more details.                     *
16   	 *                                                                          *
17   	 *  You should have received a copy of the GNU Lesser General Public        *
18   	 *  License along with DMTCP:dmtcp/src.  If not, see                        *
19   	 *  <http://www.gnu.org/licenses/>.                                         *
20   	 ****************************************************************************/
21   	
22   	#ifndef JASSERT_H
23   	#define JASSERT_H
24   	
25   	
26   	#include "stlwrapper.h"
27   	#include <string>
28   	#include <iostream>
29   	#include <sstream>
30   	#include <string.h>
31   	#include <unistd.h>
32   	#include <errno.h>
33   	#include <execinfo.h> /* For backtrace() */
34   	#define BT_SIZE 50 /* Maximum size backtrace of stack */
35   	
36   	#ifdef HAVE_CONFIG_H
37   	# include "config.h"
38   	#endif
39   	#include "jalloc.h"
40   	
41   	extern int jassert_quiet;
42   	
43   	/**  USAGE EXAMPLE:
44   	 *
45   	 * int a=1,b=2,c=3,d=4;
46   	 *
47   	 * code:
48   	 *     JASSERT(a==b)(a)(b)(c).Text("Error a!=b program will exit");
49   	 * outputs:
50   	 *     ERROR at main.cpp:15 in main
51   	 *     Reason: JASSERT(a=b) failed
52   	 *       a = 1
53   	 *       b = 2
54   	 *       c = 3
55   	 *     Message: Error a!=b program will exit
56   	 *     Terminating...
57   	 *
58   	 *
59   	 * code:
60   	 *     JWARNING(a==b)(a)(b)(d).Text("Warning a!=b program will continue");
61   	 * outputs:
62   	 *     WARNING at main.cpp:15 in main
63   	 *     Reason: JWARNING(a=b) failed
64   	 *       a = 1
65   	 *       b = 2
66   	 *       d = 4
67   	 *     Message: Warning a!=b program will continue
68   	 *
69   	 *
70   	 * code:
71   	 *     JNOTE("Values of abcd (in the form 'a=1') will be printed below this text.")(a)(b)(c)(d);
72   	 * outputs:
73   	 *     JNOTE at main.cpp:15 in main
74   	 *     Reason: Values of abcd (in the form 'a=1') will be printed below this text.
75   	 *       a = 1
76   	 *       b = 2
77   	 *       c = 3
78   	 *       d = 4
79   	 *
80   	 *
81   	 * It has the ability to output any variable understood by std::ostream.
82   	 *
83   	 */
84   	
85   	namespace jassert_internal
86   	{
87   	
88   	  class JAssert
89   	  {
90   	    public:
91   	#ifdef JALIB_ALLOCATOR
92   	      static void* operator new(size_t nbytes, void* p) { return p; }
93   	      static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
94   	      static void  operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
95   	#endif
96   	      ///
97   	      /// print a value of any type
98   	      template < typename T > JAssert& Print ( const T& t );
99   	      ///
100  	      /// print out a string in format "Message: msg"
101  	      JAssert& Text ( const char* msg );
102  	      ///
103  	      /// prints stack backtrace and always returns true
104  	      JAssert& jbacktrace ();
105  	      ///
106  	      /// constructor: sets members
107  	      JAssert ( bool exitWhenDone );
108  	      ///
109  	      /// destructor: exits program if exitWhenDone is set
110  	      ~JAssert();
111  	      ///
112  	      /// termination point for crazy macros
113  	      JAssert& JASSERT_CONT_A;
114  	      ///
115  	      /// termination point for crazy macros
116  	      JAssert& JASSERT_CONT_B;
117  	
118  	      template < typename T > JAssert& operator << ( const T& t )
119  	      { Print ( t ); return *this; }
120  	    private:
121  	      ///
122  	      /// if set true (on construction) call exit() on destruction
123  	      bool _exitWhenDone;
124  	      bool _logLockAcquired;
125  	      dmtcp::ostringstream ss;
126  	  };
127  	
128  	
129  	  const char* jassert_basename ( const char* str );
130  	  dmtcp::ostream& jassert_output_stream();
131  	  void jassert_safe_print ( const char* );
132  	  void jassert_init ( const jalib::string& f );
133  	  bool lockLog();
134  	  void unlockLog();
135  	
136  	  template < typename T >
Event noescape: "jassert_internal::JAssert &jassert_internal::JAssert::Print<char *>(char * const &)" does not free or save its pointer parameter "t".
137  	  inline JAssert& JAssert::Print ( const T& t )
138  	  {
139  	#ifdef JASSERT_FAST
140  	    jassert_output_stream() << t;
141  	#else
142  	    //dmtcp::ostringstream ss;
143  	    ss << t;
144  	    //jassert_safe_print ( ss.str().c_str() );
145  	#endif
146  	    return *this;
147  	  }
148  	
149  	  void set_log_file ( const jalib::string& path );
150  	  void reset_on_fork ( );
151  	
152  	  int jassert_console_fd();
153  	
154  	}//jassert_internal
155  	
156  	#define JASSERT_INIT(p) (jassert_internal::jassert_init(p));
157  	
158  	#define JASSERT_SET_LOGFILE(p) (jassert_internal::set_log_file(p));
159  	#define JASSERT_RESET_ON_FORK() (jassert_internal::reset_on_fork());
160  	
161  	#define JASSERT_CKPT_LOCK() (jassert_internal::lockLog());
162  	#define JASSERT_CKPT_UNLOCK() (jassert_internal::unlockLog());
163  	
164  	#define JASSERT_ERRNO (strerror(errno))
165  	
166  	#define JASSERT_PRINT(str) jassert_internal::JAssert(false).Print(str)
167  	#define JASSERT_STDERR      jassert_internal::JAssert(false)
168  	#define JASSERT_STDERR_FD   (jassert_internal::jassert_console_fd())
169  	
170  	#define JASSERT_CONT(AB,term) Print("     " #term " = ").Print(term).Print("\n").JASSERT_CONT_##AB
171  	#define JASSERT_CONT_A(term) JASSERT_CONT(B,term)
172  	#define JASSERT_CONT_B(term) JASSERT_CONT(A,term)
173  	
174  	#define JASSERT_STRINGIFY_(x) #x
175  	#define JASSERT_STRINGIFY(x) JASSERT_STRINGIFY_(x)
176  	#define JASSERT_FUNC __FUNCTION__
177  	#define JASSERT_LINE JASSERT_STRINGIFY(__LINE__)
178  	#define JASSERT_FILE jassert_internal::jassert_basename(__FILE__)
179  	#define JASSERT_CONTEXT(type,reason) Print('[').Print(getpid()).Print("] " type " at ").Print(JASSERT_FILE).Print(":" JASSERT_LINE " in ").Print(JASSERT_FUNC).Print("; REASON='" reason "'\n")
180  	
181  	#ifdef DEBUG
182  	#define JTRACE(msg) jassert_internal::JAssert(false).JASSERT_CONTEXT("TRACE",msg).JASSERT_CONT_A
183  	#else
184  	#define JTRACE(msg) if(true){}else jassert_internal::JAssert(false).JASSERT_CONTEXT("NOTE",msg).JASSERT_CONT_A
185  	#endif
186  	
187  	#ifdef QUIET
188  	#define JNOTE(msg) if(true){}else jassert_internal::JAssert(false).JASSERT_CONTEXT("NOTE",msg).JASSERT_CONT_A
189  	#else
190  	#define JNOTE(msg) if(jassert_quiet >= 1){}else \
191  	    jassert_internal::JAssert(false).JASSERT_CONTEXT("NOTE",msg).JASSERT_CONT_A
192  	#endif
193  	
194  	#ifdef QUIET
195  	#define JWARNING(term) if(true){}else \
196  	    jassert_internal::JAssert(false).JASSERT_CONTEXT("WARNING","JWARNING(" #term ") failed").JASSERT_CONT_A
197  	#else
198  	#define JWARNING(term) if((term) || jassert_quiet >= 2){}else \
199  	    jassert_internal::JAssert(false).JASSERT_CONTEXT("WARNING","JWARNING(" #term ") failed").JASSERT_CONT_A
200  	#endif
201  	
202  	#ifndef DEBUG
203  	# define JASSERT(term)  if((term)){}else \
204  	    jassert_internal::JAssert(true) \
205  		.JASSERT_CONTEXT("ERROR","JASSERT(" #term ") failed").JASSERT_CONT_A
206  	#else
207  	# define JASSERT(term) \
208  	    if ((term)) {} else \
209  	      jassert_internal::JAssert(true) \
210  	        .JASSERT_CONTEXT("ERROR","JASSERT(" #term ") failed").JASSERT_CONT_A
211  	#endif
212  	
213  	#define JALIB_CKPT_LOCK() do{\
214  	  JASSERT_CKPT_LOCK();\
215  	  JALLOC_HELPER_LOCK();\
216  	} while(0)
217  	
218  	#define JALIB_CKPT_UNLOCK() do{\
219  	  JALLOC_HELPER_UNLOCK();\
220  	  JASSERT_CKPT_UNLOCK();\
221  	} while(0)
222  	
223  	#define JALIB_RESET_ON_FORK() do{\
224  	  JASSERT_RESET_ON_FORK();\
225  	  JALLOC_HELPER_RESET_ON_FORK();\
226  	} while(0)
227  	
228  	#endif