Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_EXCEPTION_MACROS_H_ 00002 #define SimTK_SimTKCOMMON_EXCEPTION_MACROS_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2005-12 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00076 #include "SimTKcommon/internal/common.h" 00077 #include "SimTKcommon/internal/Exception.h" 00078 00079 #include <string> 00080 #include <iostream> 00081 #include <exception> 00082 00083 // --------------------------------- RANGECHECK -------------------------------- 00084 // These exceptions are to be used for situations in which a user of a SimTK 00085 // API method screws up by providing bad indices or dimensions. These are special 00086 // cases of the more general APIARGCHECK macros, providing "canned" error messages 00087 // for several common situations. Although there are several different macro 00088 // names here, all are controlled by SimTK_KEEP_RANGECHECK to allow enabling of 00089 // these index- and size-validating tests together in Release mode. 00090 // 00091 // INDEXCHECK: Note that we allow the index to be equal to the lower 00092 // bound (zero) but it must be strictly less than the upper bound. 00093 // SIZECHECK: A size or size expression must be >= 0 and less than OR EQUAL 00094 // to the maximum size. 00095 // SIZECHECK_NONNEG: A size argument must be >= 0. 00096 // VALUECHECK: A floating point is required to be within a certain range. 00097 // VALUECHECK_NONNEG: A floating point argument must be non-negative. 00098 // 00099 // TODO: SHAPECHECK, DOMAINCHECK 00100 // ----------------------------------------------------------------------------- 00101 00102 // This is a rangecheck that is always present, even in Release mode. This may be 00103 // applied both to signed and unsigned types (the latter are always nonnegative) so 00104 // to avoid warnings we use the isIndexInRange() method which doesn't perform 00105 // a nonnegativity check on unsigned quantities. 00106 #define SimTK_INDEXCHECK_ALWAYS(ix,ub,where) \ 00107 do{if(!isIndexInRange((ix),(ub)))SimTK_THROW5(SimTK::Exception::IndexOutOfRange, \ 00108 #ix,0,(ix),(ub),(where));}while(false) 00109 00110 // This is a rangecheck that is always present, even in Release mode. This may be 00111 // applied both to signed and unsigned types (the latter are always nonnegative) so 00112 // to avoid warnings we use the isSizeInRange() method which doesn't perform 00113 // a nonnegativity check on unsigned quantities. 00114 #define SimTK_SIZECHECK_ALWAYS(sz,maxsz,where) \ 00115 do{if(!isSizeInRange((sz),(maxsz)))SimTK_THROW4(SimTK::Exception::SizeOutOfRange, \ 00116 #sz,(sz),(maxsz),(where));}while(false) 00117 00118 // This is a rangecheck that is always present, even in Release mode. Use 00119 // isNonnegative() here in case sz is an unsigned type to avoid compiler 00120 // warning. 00121 #define SimTK_SIZECHECK_NONNEG_ALWAYS(sz,where) \ 00122 do{if(!isNonnegative(sz))SimTK_THROW3(SimTK::Exception::SizeWasNegative, \ 00123 #sz,(sz),(where));}while(false) 00124 00125 // Similar checks for floating point values. 00126 00127 #define SimTK_VALUECHECK_ALWAYS(lb,val,ub,valName,where) \ 00128 do{if(!(lb)<=(val)&&(val)<=(ub)))SimTK_THROW5(SimTK::Exception::ValueOutOfRange, \ 00129 (valName),(lb),(val),(ub),(where));}while(false) 00130 00131 00132 #define SimTK_VALUECHECK_NONNEG_ALWAYS(val,valName,where) \ 00133 do{if((val)<0)SimTK_THROW3(SimTK::Exception::ValueWasNegative, \ 00134 (valName),(val),(where));}while(false) 00135 00136 00137 00138 #if defined(NDEBUG) && !defined(SimTK_KEEP_RANGECHECK) 00139 #define SimTK_INDEXCHECK(ix,ub,where) 00140 #define SimTK_SIZECHECK(sz,maxsz,where) 00141 #define SimTK_SIZECHECK_NONNEG(sz,where) 00142 #define SimTK_VALUECHECK(lb,val,ub,valName,where) 00143 #define SimTK_VALUECHECK_NONNEG(val,valName,where) 00144 #else 00145 #define SimTK_INDEXCHECK(ix,ub,where) SimTK_INDEXCHECK_ALWAYS(ix,ub,where) 00146 #define SimTK_SIZECHECK(sz,maxsz,where) SimTK_SIZECHECK_ALWAYS(sz,maxsz,where) 00147 #define SimTK_SIZECHECK_NONNEG(sz,where) SimTK_SIZECHECK_NONNEG_ALWAYS(sz,where) 00148 #define SimTK_VALUECHECK(lb,val,ub,valName,where) SimTK_VALUECHECK_ALWAYS(lb,val,ub,valName,where) 00149 #define SimTK_VALUECHECK_NONNEG(val,valName,where) SimTK_VALUECHECK_NONNEG_ALWAYS(val,valName,where) 00150 #endif 00151 00152 00153 // --------------------------------- STAGECHECK -------------------------------- 00154 // These exceptions are to be used for situations in which a 00155 // user of an API screws up by attempting to access something in the 00156 // state before it has been realized to the appropriate stage. 00157 // 00158 // STAGECHECK_TOPOLOGY_REALIZED: Check that realizeTopology() has been done 00159 // since the last topological change. 00160 // STAGECHECK_EQ: Check that the current stage is == a particular stage. 00161 // STAGECHECK_GE: Check that the current stage is >= a particular stage. 00162 // STAGECHECK_LT: Check that the current stage is < a particular stage. 00163 // STAGECHECK_RANGE: Check that lower <= stage <= upper. 00164 // ----------------------------------------------------------------------------- 00165 00166 // These are stagechecks that is always present, even in Release mode. 00167 #define SimTK_STAGECHECK_TOPOLOGY_REALIZED_ALWAYS(cond,objType,objName,methodNm) \ 00168 do{if(!(cond)) SimTK_THROW3(SimTK::Exception::RealizeTopologyMustBeCalledFirst, \ 00169 (objType),(objName),(methodNm));}while(false) 00170 #define SimTK_STAGECHECK_TOPOLOGY_VERSION_ALWAYS(sysTopoVersion, \ 00171 stateTopoVersion,objType,objName,methodNm) \ 00172 do{if((stateTopoVersion)!=(sysTopoVersion)) \ 00173 SimTK_THROW5(SimTK::Exception::StateAndSystemTopologyVersionsMustMatch, \ 00174 (objType),(objName),(methodNm), \ 00175 (int)(sysTopoVersion),(int)(stateTopoVersion));} \ 00176 while(false) 00177 #define SimTK_STAGECHECK_EQ_ALWAYS(currentStage,targetStage,methodNm) \ 00178 do{if((currentStage)!=(targetStage)) SimTK_THROW3(SimTK::Exception::StageIsWrong, \ 00179 (currentStage),(targetStage),(methodNm));}while(false) 00180 #define SimTK_STAGECHECK_GE_ALWAYS(currentStage,targetStage,methodNm) \ 00181 do{if(!((currentStage)>=(targetStage))) SimTK_THROW3(SimTK::Exception::StageTooLow, \ 00182 (currentStage),(targetStage),(methodNm));}while(false) 00183 #define SimTK_STAGECHECK_LT_ALWAYS(currentStage,targetStage,methodNm) \ 00184 do{if((currentStage)>=(targetStage)) SimTK_THROW3(SimTK::Exception::StageTooHigh, \ 00185 (currentStage),(targetStage),(methodNm));}while(false) 00186 #define SimTK_STAGECHECK_RANGE_ALWAYS(lower,current,upper,methodNm) \ 00187 do{if(!((lower)<=(current)&&(current)<=(upper))) SimTK_THROW4(SimTK::Exception::StageOutOfRange, \ 00188 (lower),(current),(upper),(methodNm));}while(false) 00189 00190 // This one is present only in Debug mode or if SimTK_KEEP_STAGECHECK is explicitly defined. 00191 #if defined(NDEBUG) && !defined(SimTK_KEEP_STAGECHECK) 00192 #define SimTK_STAGECHECK_TOPOLOGY_REALIZED(cond,objType,objName,methodName) 00193 #define SimTK_STAGECHECK_TOPOLOGY_VERSIONS(sysTopoVersion,stateTopoVersion,\ 00194 objType,objName,methodNm) 00195 #define SimTK_STAGECHECK_EQ(currentStage,targetStage,methodNm) 00196 #define SimTK_STAGECHECK_GE(currentStage,targetStage,methodNm) 00197 #define SimTK_STAGECHECK_LT(currentStage,targetStage,methodNm) 00198 #define SimTK_STAGECHECK_RANGE(lower,current,upper,methodNm) 00199 #else 00200 #define SimTK_STAGECHECK_TOPOLOGY_REALIZED(cond,objType,objName,methodName) \ 00201 SimTK_STAGECHECK_TOPOLOGY_REALIZED_ALWAYS(cond,objType,objName,methodName) 00202 #define SimTK_STAGECHECK_TOPOLOGY_VERSION(sysTopoVersion,stateTopoVersion, \ 00203 objType,objName,methodNm) \ 00204 SimTK_STAGECHECK_TOPOLOGY_VERSION_ALWAYS(sysTopoVersion,stateTopoVersion,\ 00205 objType,objName,methodNm) 00206 #define SimTK_STAGECHECK_EQ(currentStage,targetStage,methodNm) \ 00207 SimTK_STAGECHECK_EQ_ALWAYS(currentStage,targetStage,methodNm) 00208 #define SimTK_STAGECHECK_GE(currentStage,targetStage,methodNm) \ 00209 SimTK_STAGECHECK_GE_ALWAYS(currentStage,targetStage,methodNm) 00210 #define SimTK_STAGECHECK_LT(currentStage,targetStage,methodNm) \ 00211 SimTK_STAGECHECK_LE_ALWAYS(currentStage,targetStage,methodNm) 00212 #define SimTK_STAGECHECK_RANGE(lower,current,upper,methodNm) \ 00213 SimTK_STAGECHECK_RANGE_ALWAYS(lower,current,upper,methodNm) 00214 #endif 00215 00216 // -------------------------------- APIARGCHECK -------------------------------- 00217 // These should be used to catch all manner of problems with the arguments passed 00218 // in an API user's call to a method that is part of a SimTK API. Note that these 00219 // are intended for direct consumption by an application programmer using a SimTK 00220 // API, so should be wordy and helpful. These macros accept printf-style format 00221 // strings and arguments of whatever are the appropriate types for those formats. 00222 // ----------------------------------------------------------------------------- 00223 00224 #define SimTK_APIARGCHECK_ALWAYS(cond,className,methodName,msg) \ 00225 do{if(!(cond))SimTK_THROW4(SimTK::Exception::APIArgcheckFailed, \ 00226 #cond,(className),(methodName),(msg)); \ 00227 }while(false) 00228 #define SimTK_APIARGCHECK1_ALWAYS(cond,className,methodName,fmt,a1) \ 00229 do{if(!(cond))SimTK_THROW5(SimTK::Exception::APIArgcheckFailed, \ 00230 #cond,(className),(methodName),(fmt),(a1)); \ 00231 }while(false) 00232 #define SimTK_APIARGCHECK2_ALWAYS(cond,className,methodName,fmt,a1,a2) \ 00233 do{if(!(cond))SimTK_THROW6(SimTK::Exception::APIArgcheckFailed, \ 00234 #cond,(className),(methodName),(fmt),(a1),(a2)); \ 00235 }while(false) 00236 #define SimTK_APIARGCHECK3_ALWAYS(cond,className,methodName,fmt,a1,a2,a3) \ 00237 do{if(!(cond))SimTK_THROW7(SimTK::Exception::APIArgcheckFailed, \ 00238 #cond,(className),(methodName),(fmt),(a1),(a2),(a3)); \ 00239 }while(false) 00240 #define SimTK_APIARGCHECK4_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4) \ 00241 do{if(!(cond))SimTK_THROW8(SimTK::Exception::APIArgcheckFailed, \ 00242 #cond,(className),(methodName),(fmt),(a1),(a2),(a3),(a4)); \ 00243 }while(false) 00244 #define SimTK_APIARGCHECK5_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4,a5) \ 00245 do{if(!(cond))SimTK_THROW9(SimTK::Exception::APIArgcheckFailed, \ 00246 #cond,(className),(methodName),(fmt),(a1),(a2),(a3),(a4),(a5)); \ 00247 }while(false) 00248 00249 #if defined(NDEBUG) && !defined(SimTK_KEEP_APIARGCHECK) 00250 #define SimTK_APIARGCHECK(cond,className,methodName,msg) 00251 #define SimTK_APIARGCHECK1(cond,className,methodName,fmt,a1) 00252 #define SimTK_APIARGCHECK2(cond,className,methodName,fmt,a1,a2) 00253 #define SimTK_APIARGCHECK3(cond,className,methodName,fmt,a1,a2,a3) 00254 #define SimTK_APIARGCHECK4(cond,className,methodName,fmt,a1,a2,a3,a4) 00255 #define SimTK_APIARGCHECK5(cond,className,methodName,fmt,a1,a2,a3,a4,a5) 00256 #else 00257 #define SimTK_APIARGCHECK(cond,className,methodName,msg) \ 00258 SimTK_APIARGCHECK_ALWAYS(cond,className,methodName,msg) 00259 #define SimTK_APIARGCHECK1(cond,className,methodName,fmt,a1) \ 00260 SimTK_APIARGCHECK1_ALWAYS(cond,className,methodName,fmt,a1) 00261 #define SimTK_APIARGCHECK2(cond,className,methodName,fmt,a1,a2) \ 00262 SimTK_APIARGCHECK2_ALWAYS(cond,className,methodName,fmt,a1,a2) 00263 #define SimTK_APIARGCHECK3(cond,className,methodName,fmt,a1,a2,a3) \ 00264 SimTK_APIARGCHECK3_ALWAYS(cond,className,methodName,fmt,a1,a2,a3) 00265 #define SimTK_APIARGCHECK4(cond,className,methodName,fmt,a1,a2,a3,a4) \ 00266 SimTK_APIARGCHECK4_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4) 00267 #define SimTK_APIARGCHECK5(cond,className,methodName,fmt,a1,a2,a3,a4,a5) \ 00268 SimTK_APIARGCHECK5_ALWAYS(cond,className,methodName,fmt,a1,a2,a3,a4,a5) 00269 #endif 00270 00271 00272 // ----------------------------------- ERRCHK ---------------------------------- 00273 // ERRCHK: these should be used to catch all manner of problems that occur 00274 // during execution of an API user's request by a method that is part of 00275 // a SimTK API. Note that these are intended for direct consumption by 00276 // an application programmer using a SimTK API, so should be wordy and 00277 // helpful. These macros accept printf-style format strings and arguments 00278 // of whatever are the appropriate types for those formats. 00279 // ----------------------------------------------------------------------------- 00280 00281 #define SimTK_ERRCHK_ALWAYS(cond,whereChecked,msg) \ 00282 do{if(!(cond))SimTK_THROW3(SimTK::Exception::ErrorCheck, \ 00283 #cond,(whereChecked),(msg)); \ 00284 }while(false) 00285 #define SimTK_ERRCHK1_ALWAYS(cond,whereChecked,fmt,a1) \ 00286 do{if(!(cond))SimTK_THROW4(SimTK::Exception::ErrorCheck, \ 00287 #cond,(whereChecked),(fmt),(a1)); \ 00288 }while(false) 00289 #define SimTK_ERRCHK2_ALWAYS(cond,whereChecked,fmt,a1,a2) \ 00290 do{if(!(cond))SimTK_THROW5(SimTK::Exception::ErrorCheck, \ 00291 #cond,(whereChecked),(fmt),(a1),(a2)); \ 00292 }while(false) 00293 #define SimTK_ERRCHK3_ALWAYS(cond,whereChecked,fmt,a1,a2,a3) \ 00294 do{if(!(cond))SimTK_THROW6(SimTK::Exception::ErrorCheck, \ 00295 #cond,(whereChecked),(fmt),(a1),(a2),(a3)); \ 00296 }while(false) 00297 #define SimTK_ERRCHK4_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4) \ 00298 do{if(!(cond))SimTK_THROW7(SimTK::Exception::ErrorCheck, \ 00299 #cond,(whereChecked),(fmt),(a1),(a2),(a3),(a4)); \ 00300 }while(false) 00301 #define SimTK_ERRCHK5_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5) \ 00302 do{if(!(cond))SimTK_THROW8(SimTK::Exception::ErrorCheck, \ 00303 #cond,(whereChecked),(fmt),(a1),(a2),(a3),(a4),(a5)); \ 00304 }while(false) 00305 #define SimTK_ERRCHK6_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6) \ 00306 do{if(!(cond))SimTK_THROW9(SimTK::Exception::ErrorCheck, \ 00307 #cond,(whereChecked),(fmt),(a1),(a2),(a3),(a4),(a5),(a6)); \ 00308 }while(false) 00309 #define SimTK_ERRCHK7_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6,a7) \ 00310 do{if(!(cond))SimTK_THROW10(SimTK::Exception::ErrorCheck, \ 00311 #cond,(whereChecked),(fmt),(a1),(a2),(a3),(a4),(a5),(a6),(a7)); \ 00312 }while(false) 00313 00314 #if defined(NDEBUG) && !defined(SimTK_KEEP_ERRCHK) 00315 #define SimTK_ERRCHK(cond,whereChecked,msg) 00316 #define SimTK_ERRCHK1(cond,whereChecked,fmt,a1) 00317 #define SimTK_ERRCHK2(cond,whereChecked,fmt,a1,a2) 00318 #define SimTK_ERRCHK3(cond,whereChecked,fmt,a1,a2,a3) 00319 #define SimTK_ERRCHK4(cond,whereChecked,fmt,a1,a2,a3,a4) 00320 #define SimTK_ERRCHK5(cond,whereChecked,fmt,a1,a2,a3,a4,a5) 00321 #define SimTK_ERRCHK6(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6) 00322 #define SimTK_ERRCHK7(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6) 00323 #else 00324 #define SimTK_ERRCHK(cond,whereChecked,msg) \ 00325 SimTK_ERRCHK_ALWAYS(cond,whereChecked,msg) 00326 #define SimTK_ERRCHK1(cond,whereChecked,fmt,a1) \ 00327 SimTK_ERRCHK1_ALWAYS(cond,whereChecked,fmt,a1) 00328 #define SimTK_ERRCHK2(cond,whereChecked,fmt,a1,a2) \ 00329 SimTK_ERRCHK2_ALWAYS(cond,whereChecked,fmt,a1,a2) 00330 #define SimTK_ERRCHK3(cond,whereChecked,fmt,a1,a2,a3) \ 00331 SimTK_ERRCHK3_ALWAYS(cond,whereChecked,fmt,a1,a2,a3) 00332 #define SimTK_ERRCHK4(cond,whereChecked,fmt,a1,a2,a3,a4) \ 00333 SimTK_ERRCHK4_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4) 00334 #define SimTK_ERRCHK5(cond,whereChecked,fmt,a1,a2,a3,a4,a5) \ 00335 SimTK_ERRCHK5_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5) 00336 #define SimTK_ERRCHK6(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6) \ 00337 SimTK_ERRCHK6_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6) 00338 #define SimTK_ERRCHK7(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6,a7) \ 00339 SimTK_ERRCHK7_ALWAYS(cond,whereChecked,fmt,a1,a2,a3,a4,a5,a6,a7) 00340 #endif 00341 00342 // ----------------------------------- ASSERT ---------------------------------- 00343 // ASSERT: use this *only* for internal errors, that is, bugs. This must 00344 // not be used to catch usage errors by clients; if you want to catch 00345 // user errors use different exceptions. 00346 // ----------------------------------------------------------------------------- 00347 00348 // This is an assertion that is always active, even in Release mode. 00349 #define SimTK_ASSERT_ALWAYS(cond,msg) \ 00350 do{if(!(cond))SimTK_THROW2(SimTK::Exception::Assert,#cond,(msg));}while(false) 00351 #define SimTK_ASSERT1_ALWAYS(cond,msg,a1) \ 00352 do{if(!(cond))SimTK_THROW3(SimTK::Exception::Assert,#cond,(msg),(a1));}while(false) 00353 #define SimTK_ASSERT2_ALWAYS(cond,msg,a1,a2) \ 00354 do{if(!(cond))SimTK_THROW4(SimTK::Exception::Assert,#cond,(msg),(a1),(a2));}while(false) 00355 #define SimTK_ASSERT3_ALWAYS(cond,msg,a1,a2,a3) \ 00356 do{if(!(cond))SimTK_THROW5(SimTK::Exception::Assert,#cond,(msg),(a1),(a2),(a3));}while(false) 00357 #define SimTK_ASSERT4_ALWAYS(cond,msg,a1,a2,a3,a4) \ 00358 do{if(!(cond))SimTK_THROW6(SimTK::Exception::Assert,#cond,(msg),(a1),(a2),(a3),(a4));}while(false) 00359 #define SimTK_ASSERT5_ALWAYS(cond,msg,a1,a2,a3,a4,a5) \ 00360 do{if(!(cond))SimTK_THROW7(SimTK::Exception::Assert,#cond,(msg),(a1),(a2),(a3),(a4),(a5));}while(false) 00361 00362 // Note: unlike the system assert() we're putting ours within the header guards. 00363 // So if you want to override NDEBUG do it at the *beginning* (that is, before 00364 // the first #include or #ifdef) of whatever compilation unit you are fiddling with. 00365 #if defined(NDEBUG) && !defined(SimTK_KEEP_ASSERT) 00366 #define SimTK_ASSERT(cond,msg) 00367 #define SimTK_ASSERT(cond,msg) 00368 #define SimTK_ASSERT1(cond,msg,a1) 00369 #define SimTK_ASSERT2(cond,msg,a1,a2) 00370 #define SimTK_ASSERT3(cond,msg,a1,a2,a3) 00371 #define SimTK_ASSERT4(cond,msg,a1,a2,a3,a4) 00372 #define SimTK_ASSERT5(cond,msg,a1,a2,a3,a4,a5) 00373 #else 00374 #define SimTK_ASSERT(cond,msg) SimTK_ASSERT_ALWAYS(cond,msg) 00375 #define SimTK_ASSERT1(cond,msg,a1) SimTK_ASSERT1_ALWAYS(cond,msg,a1) 00376 #define SimTK_ASSERT2(cond,msg,a1,a2) SimTK_ASSERT2_ALWAYS(cond,msg,a1,a2) 00377 #define SimTK_ASSERT3(cond,msg,a1,a2,a3) SimTK_ASSERT3_ALWAYS(cond,msg,a1,a2,a3) 00378 #define SimTK_ASSERT4(cond,msg,a1,a2,a3,a4) SimTK_ASSERT4_ALWAYS(cond,msg,a1,a2,a3,a4) 00379 #define SimTK_ASSERT5(cond,msg,a1,a2,a3,a4,a5) SimTK_ASSERT5_ALWAYS(cond,msg,a1,a2,a3,a4,a5) 00380 #endif 00381 00382 00383 #endif // SimTK_SimTKCOMMON_EXCEPTION_MACROS_H_ 00384 00385 00386