00001 /** @file rutz/debug.cc debugging facilities, assertions, 00002 preconditions, postconditions, invariants */ 00003 /////////////////////////////////////////////////////////////////////// 00004 // 00005 // Copyright (c) 2000-2004 California Institute of Technology 00006 // Copyright (c) 2004-2007 University of Southern California 00007 // Rob Peters <rjpeters at usc dot edu> 00008 // 00009 // created: Mon Oct 9 18:48:38 2000 00010 // commit: $Id: debug.cc 12074 2009-11-24 07:51:51Z itti $ 00011 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/debug.cc $ 00012 // 00013 // -------------------------------------------------------------------- 00014 // 00015 // This file is part of GroovX. 00016 // [http://ilab.usc.edu/rjpeters/groovx/] 00017 // 00018 // GroovX is free software; you can redistribute it and/or modify it 00019 // under the terms of the GNU General Public License as published by 00020 // the Free Software Foundation; either version 2 of the License, or 00021 // (at your option) any later version. 00022 // 00023 // GroovX is distributed in the hope that it will be useful, but 00024 // WITHOUT ANY WARRANTY; without even the implied warranty of 00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00026 // General Public License for more details. 00027 // 00028 // You should have received a copy of the GNU General Public License 00029 // along with GroovX; if not, write to the Free Software Foundation, 00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00031 // 00032 /////////////////////////////////////////////////////////////////////// 00033 00034 #ifndef GROOVX_RUTZ_DEBUG_CC_UTC20050626084020_DEFINED 00035 #define GROOVX_RUTZ_DEBUG_CC_UTC20050626084020_DEFINED 00036 00037 #include "rutz/debug.h" 00038 GVX_DBG_REGISTER 00039 00040 #include "rutz/backtrace.h" 00041 #include "rutz/mutex.h" 00042 00043 #include <cstdlib> 00044 #include <cstring> 00045 #include <iomanip> 00046 #include <iostream> 00047 00048 #include <cstdio> 00049 #include <cerrno> 00050 00051 namespace 00052 { 00053 const int MAX_KEYS = 1024; 00054 00055 // output-related variables and guard mutex 00056 bool g_debug_line_complete = true; 00057 pthread_mutex_t g_debug_output_mutex = PTHREAD_MUTEX_INITIALIZER; 00058 00059 // debug keys and guard mutex 00060 int g_debug_next_key = 0; 00061 unsigned char g_key_levels[MAX_KEYS]; 00062 const char* g_key_filenames[MAX_KEYS]; 00063 pthread_mutex_t g_debug_keys_mutex = PTHREAD_MUTEX_INITIALIZER; 00064 00065 void show_position(int level, const char* where, int line_no) throw() 00066 { 00067 std::cerr << "[" << std::setw(2) << level << "] " 00068 << std::setw(20) << where << ":" 00069 << line_no << ": "; 00070 } 00071 } 00072 00073 #define EVAL_IMPL(T) \ 00074 void rutz::debug::eval(const char* what, int level, \ 00075 const char* where, int line_no, \ 00076 bool nl, T expr) throw() \ 00077 { \ 00078 GVX_MUTEX_LOCK(&g_debug_output_mutex); \ 00079 using std::cerr; \ 00080 cerr.exceptions(std::ios::goodbit); \ 00081 if (g_debug_line_complete) \ 00082 { \ 00083 show_position(level, where, line_no); \ 00084 } \ 00085 if (what) \ 00086 { \ 00087 cerr << "(" << #T << ") " << what << " = "; \ 00088 } \ 00089 cerr << expr; \ 00090 if (nl) \ 00091 { \ 00092 cerr << "\n"; \ 00093 g_debug_line_complete = true; \ 00094 } \ 00095 else \ 00096 { \ 00097 cerr << ", "; \ 00098 g_debug_line_complete = false; \ 00099 } \ 00100 } 00101 00102 EVAL_IMPL(bool); 00103 EVAL_IMPL(char); 00104 EVAL_IMPL(unsigned char); 00105 EVAL_IMPL(short); 00106 EVAL_IMPL(unsigned short); 00107 EVAL_IMPL(int); 00108 EVAL_IMPL(unsigned int); 00109 EVAL_IMPL(long); 00110 EVAL_IMPL(unsigned long); 00111 EVAL_IMPL(float); 00112 EVAL_IMPL(double); 00113 EVAL_IMPL(const char*); 00114 EVAL_IMPL(void*); 00115 00116 void rutz::debug::dump(const char* what, int level, const char* where, int line_no) throw() 00117 { 00118 GVX_MUTEX_LOCK(&g_debug_output_mutex); 00119 std::cerr.exceptions(std::ios::goodbit); 00120 show_position(level, where, line_no); 00121 std::cerr << std::setw(15) << what << " := "; 00122 g_debug_line_complete = false; 00123 } 00124 00125 void rutz::debug::start_newline() throw() 00126 { 00127 GVX_MUTEX_LOCK(&g_debug_output_mutex); 00128 std::cerr.exceptions(std::ios::goodbit); 00129 if (!g_debug_line_complete) 00130 { 00131 std::cerr << '\n'; 00132 g_debug_line_complete = true; 00133 } 00134 } 00135 00136 void rutz::debug::panic_aux(const char* what, const char* where, 00137 int line_no) throw() 00138 { 00139 fprintf(stderr, "Panic (%s:%d):\n\t%s\n\n", 00140 where, line_no, what); 00141 rutz::backtrace::current().print(); 00142 abort(); 00143 } 00144 00145 void rutz::debug::assert_aux(const char* what, const char* where, 00146 int line_no) throw() 00147 { 00148 fprintf(stderr, "Assertion failed (%s:%d):\n\texpected '%s'\n\n", 00149 where, line_no, what); 00150 rutz::backtrace::current().print(); 00151 abort(); 00152 } 00153 00154 void rutz::debug::precondition_aux(const char* what, const char* where, 00155 int line_no) throw() 00156 { 00157 fprintf(stderr, "Precondition failed (%s:%d):\n\texpected '%s'\n\n", 00158 where, line_no, what); 00159 rutz::backtrace::current().print(); 00160 abort(); 00161 } 00162 00163 void rutz::debug::postcondition_aux(const char* what, const char* where, 00164 int line_no) throw() 00165 { 00166 fprintf(stderr, "Postcondition failed (%s:%d):\n\texpected '%s'\n\n", 00167 where, line_no, what); 00168 rutz::backtrace::current().print(); 00169 abort(); 00170 } 00171 00172 void rutz::debug::invariant_aux(const char* what, const char* where, 00173 int line_no) throw() 00174 { 00175 fprintf(stderr, "Invariant failed (%s:%d):\n\texpected '%s'\n\n", 00176 where, line_no, what); 00177 rutz::backtrace::current().print(); 00178 abort(); 00179 } 00180 00181 int rutz::debug::create_key(const char* filename) 00182 { 00183 GVX_MUTEX_LOCK(&g_debug_keys_mutex); 00184 const int key = g_debug_next_key; 00185 g_key_filenames[key] = filename; 00186 if (g_debug_next_key < (MAX_KEYS-1)) 00187 ++g_debug_next_key; 00188 return key; 00189 } 00190 00191 bool rutz::debug::is_valid_key(int key) 00192 { 00193 return key >= 0 && key < MAX_KEYS; 00194 } 00195 00196 int rutz::debug::lookup_key(const char* filename) 00197 { 00198 GVX_MUTEX_LOCK(&g_debug_keys_mutex); 00199 for (int i = 0; i < g_debug_next_key; ++i) 00200 { 00201 if (strcmp(g_key_filenames[i], filename) == 0) 00202 return i; 00203 } 00204 return -1; 00205 } 00206 00207 int rutz::debug::get_level_for_key(int key) 00208 { 00209 GVX_MUTEX_LOCK(&g_debug_keys_mutex); 00210 if (key < MAX_KEYS) 00211 return g_key_levels[key]; 00212 return 0; 00213 } 00214 00215 void rutz::debug::set_level_for_key(int key, int level) 00216 { 00217 GVX_MUTEX_LOCK(&g_debug_keys_mutex); 00218 if (key <MAX_KEYS) 00219 g_key_levels[key] = level; 00220 } 00221 00222 const char* rutz::debug::get_filename_for_key(int key) 00223 { 00224 GVX_MUTEX_LOCK(&g_debug_keys_mutex); 00225 return g_key_filenames[key]; 00226 } 00227 00228 void rutz::debug::set_global_level(int lev) 00229 { 00230 GVX_MUTEX_LOCK(&g_debug_keys_mutex); 00231 for (int i = 0; i < MAX_KEYS; ++i) 00232 g_key_levels[i] = (unsigned char) lev; 00233 } 00234 00235 static const char __attribute__((used)) vcid_groovx_rutz_debug_cc_utc20050626084020[] = "$Id: debug.cc 12074 2009-11-24 07:51:51Z itti $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/debug.cc $"; 00236 #endif // !GROOVX_RUTZ_DEBUG_CC_UTC20050626084020_DEFINED