00001 /* $Id: irplib_utils.h,v 1.33 2007/08/08 18:36:11 llundin Exp $ 00002 * 00003 * This file is part of the irplib package 00004 * Copyright (C) 2002,2003 European Southern Observatory 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA 00019 */ 00020 00021 /* 00022 * $Author: llundin $ 00023 * $Date: 2007/08/08 18:36:11 $ 00024 * $Revision: 1.33 $ 00025 * $Name: uves-3_4_5 $ 00026 */ 00027 00028 #ifndef IRPLIB_UTILS_H 00029 #define IRPLIB_UTILS_H 00030 00031 /*----------------------------------------------------------------------------- 00032 Includes 00033 -----------------------------------------------------------------------------*/ 00034 00035 #include <stdarg.h> 00036 00037 #include <cpl.h> 00038 00039 /*----------------------------------------------------------------------------- 00040 Define 00041 -----------------------------------------------------------------------------*/ 00042 00043 /* FIXME: Remove when no longer used by any irplib-based pipelines */ 00044 #define irplib_vsprintf cpl_vsprintf 00045 #define irplib_sprintf cpl_sprintf 00046 00047 /* FIXME: Remove when no longer used by any irplib-based pipelines */ 00048 /* Useful for debugging */ 00049 #define irplib_trace() do if (cpl_error_get_code()) { \ 00050 cpl_msg_debug(cpl_func, __FILE__ " at line %d: ERROR '%s' at %s", \ 00051 __LINE__, cpl_error_get_message(), cpl_error_get_where()); \ 00052 } else { \ 00053 cpl_msg_debug(cpl_func, __FILE__ " at line %d: OK", __LINE__); \ 00054 } while (0) 00055 00056 #define irplib_error_recover(ESTATE, ...) \ 00057 do if (!cpl_errorstate_is_equal(ESTATE)) { \ 00058 cpl_msg_warning(cpl_func, __VA_ARGS__); \ 00059 cpl_msg_indent_more(); \ 00060 cpl_errorstate_dump(ESTATE, CPL_FALSE, irplib_errorstate_warning); \ 00061 cpl_msg_indent_less(); \ 00062 cpl_errorstate_set(ESTATE); \ 00063 } while (0) 00064 00065 00066 /*----------------------------------------------------------------------------*/ 00067 /* 00068 @brief Conditional skip to the (unqiue) return point of the function 00069 @param CONDITION The condition to check 00070 @see cpl_error_ensure() 00071 00072 skip_if() takes one argument, which is a logical expression. 00073 If the logical expression is false skip_if() takes no action and 00074 program execution continues. 00075 If the logical expression is true this indicates an error. In this case 00076 skip_if() will set the location of the error to the point where it 00077 was invoked in the recipe code (unless the error location is already in the 00078 recipe code). If no error code had been set, then skip_if() will set one. 00079 Finally, skip_if() causes program execution to skip to the macro 'end_skip'. 00080 The macro end_skip is located towards the end of the function, after 00081 which all resource deallocation and the function return is located. 00082 00083 The use of skip_if() assumes the following coding practice: 00084 1) Pointers used for dynamically allocated memory that they "own" shall always 00085 point to either NULL or to allocated memory (including CPL-objects). 00086 2) Such pointers may not be reused to point to memory whose deallocation 00087 requires calls to different functions. 00088 3) Pointers of type FILE should be set NULL when not pointing to an open 00089 stream and their closing calls (fclose(), freopen(), etc.) following the 00090 'end_skip' should be guarded against such NULL pointers. 00091 00092 Error checking with skip_if() is encouraged due to the following advantages: 00093 1) It ensures that a CPL-error code is set. 00094 2) It ensures that the location of the error in the _recipe_ code is noted. 00095 3) The error checking may be confined to a single concise line. 00096 4) It is not necessary to replicate memory deallocation for every error 00097 condition. 00098 5) If more extensive error reporting/handling is required it is not precluded 00099 by the use of skip_if(). 00100 6) It allows for a single point of function return. 00101 7) It allows for optional, uniformly formatted debugging/tracing information 00102 at each macro invocation. 00103 00104 The implementation of skip_if() uses a goto/label construction. 00105 According to Kerningham & Ritchie, The C Programming Language, 2nd edition, 00106 Section 3.8: 00107 "This organization is handy if the error-handling code is non-trivial, 00108 and if errors can occur in several places." 00109 00110 The use of goto for any other purpose should be avoided. 00111 00112 */ 00113 /*----------------------------------------------------------------------------*/ 00114 #define skip_if(CONDITION) \ 00115 do { \ 00116 irplib_trace(); \ 00117 cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), \ 00118 goto cleanup, "Skipping due to a pre-existing error");\ 00119 cpl_error_ensure(!(CONDITION), cpl_error_get_code(), \ 00120 goto cleanup, "Propagating error");\ 00121 } while (0) 00122 00123 /*----------------------------------------------------------------------------*/ 00124 /* 00125 @brief Skip if A < B 00126 @param A The 1st double to compare 00127 @param B The 2nd double to compare 00128 @param MSG The message to use on failure 00129 @see skip_if() 00130 @note A and B are evaluated exactly once 00131 */ 00132 /*----------------------------------------------------------------------------*/ 00133 #define skip_if_lt(A, B, MSG) \ 00134 do { \ 00135 const double tmpa = (double)(A); \ 00136 const double tmpb = (double)(B); \ 00137 \ 00138 irplib_trace(); \ 00139 cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), \ 00140 goto cleanup, "Skipping due to a pre-existing error");\ 00141 cpl_error_ensure(tmpa >= tmpb, CPL_ERROR_DATA_NOT_FOUND, \ 00142 goto cleanup, "Need at least %g (not %g) %s", \ 00143 tmpb, tmpa, MSG); \ 00144 } while (0) 00145 00146 /*----------------------------------------------------------------------------*/ 00147 /* 00148 @brief Conditional skip on coding bug 00149 @param CONDITION The condition to check 00150 @see skip_if() 00151 @note unlike assert() this check cannot be disabled 00152 */ 00153 /*----------------------------------------------------------------------------*/ 00154 #define bug_if(CONDITION) \ 00155 do { \ 00156 irplib_trace(); \ 00157 cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), \ 00158 goto cleanup, "Unexpected error, please report to " \ 00159 PACKAGE_BUGREPORT); \ 00160 cpl_error_ensure(!(CONDITION), CPL_ERROR_UNSPECIFIED, \ 00161 goto cleanup, "Internal error, please report to " \ 00162 PACKAGE_BUGREPORT); \ 00163 } while (0) 00164 00165 /*----------------------------------------------------------------------------*/ 00166 /* 00167 @brief Define the single point of resource deallocation and return 00168 @see skip_if() 00169 @note end_skip should be used exactly once in functions that use skip_if() etc 00170 */ 00171 /*----------------------------------------------------------------------------*/ 00172 #define end_skip \ 00173 do { \ 00174 cleanup: \ 00175 if (cpl_error_get_code()) \ 00176 cpl_msg_debug(cpl_func, "Cleanup in " __FILE__ " line %u with " \ 00177 "error '%s' at %s", __LINE__, \ 00178 cpl_error_get_message(), cpl_error_get_where()); \ 00179 else \ 00180 cpl_msg_debug(cpl_func, "Cleanup in " __FILE__ " line %u", \ 00181 __LINE__); \ 00182 } while (0) 00183 00184 00185 /*----------------------------------------------------------------------------*/ 00197 /*----------------------------------------------------------------------------*/ 00198 #define irplib_ensure(CONDITION, ec, ...) \ 00199 cpl_error_ensure(CONDITION, ec, goto cleanup, __VA_ARGS__) 00200 00201 /*----------------------------------------------------------------------------*/ 00231 /*----------------------------------------------------------------------------*/ 00232 00233 #define irplib_check(COMMAND, ...) \ 00234 do { \ 00235 cpl_errorstate irplib_check_prestate = cpl_errorstate_get(); \ 00236 skip_if(0); \ 00237 COMMAND; \ 00238 irplib_trace(); \ 00239 irplib_ensure(cpl_errorstate_is_equal(irplib_check_prestate), \ 00240 cpl_error_get_code(), __VA_ARGS__); \ 00241 irplib_trace(); \ 00242 } while (0) 00243 00244 /*----------------------------------------------------------------------------- 00245 Function prototypes 00246 -----------------------------------------------------------------------------*/ 00247 00248 void irplib_reset(void); 00249 int irplib_compare_tags(cpl_frame *, cpl_frame *); 00250 const char * irplib_frameset_find_file(const cpl_frameset *, const char *); 00251 cpl_frame * irplib_frameset_get_first_from_group(const cpl_frameset *, 00252 cpl_frame_group); 00253 00254 cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures *, int *, 00255 int); 00256 00257 int irplib_isinf(double value); 00258 int irplib_isnan(double value); 00259 00260 void irplib_errorstate_warning(unsigned, unsigned, unsigned); 00261 00262 #endif
1.5.1