00001 /* $Id: irplib_utils.h,v 1.41 2008/04/17 21:12:34 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: 2008/04/17 21:12:34 $ 00024 * $Revision: 1.41 $ 00025 * $Name: uves-4_2_2 $ 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 #define IRPLIB_XSTRINGIFY(TOSTRING) #TOSTRING 00044 #define IRPLIB_STRINGIFY(TOSTRING) IRPLIB_XSTRINGIFY(TOSTRING) 00045 00046 /* FIXME: Remove when no longer used by any irplib-based pipelines */ 00047 #define irplib_vsprintf cpl_vsprintf 00048 #define irplib_sprintf cpl_sprintf 00049 00050 /* FIXME: Remove when no longer used by any irplib-based pipelines */ 00051 /* Useful for debugging */ 00052 #define irplib_trace() do if (cpl_error_get_code()) { \ 00053 cpl_msg_debug(cpl_func, __FILE__ " at line %d: ERROR '%s' at %s", \ 00054 __LINE__, cpl_error_get_message(), cpl_error_get_where()); \ 00055 } else { \ 00056 cpl_msg_debug(cpl_func, __FILE__ " at line %d: OK", __LINE__); \ 00057 } while (0) 00058 00059 #define irplib_error_recover(ESTATE, ...) \ 00060 do if (!cpl_errorstate_is_equal(ESTATE)) { \ 00061 cpl_msg_warning(cpl_func, __VA_ARGS__); \ 00062 cpl_msg_indent_more(); \ 00063 cpl_errorstate_dump(ESTATE, CPL_FALSE, irplib_errorstate_warning); \ 00064 cpl_msg_indent_less(); \ 00065 cpl_errorstate_set(ESTATE); \ 00066 } while (0) 00067 00068 00069 00070 /*----------------------------------------------------------------------------*/ 00071 /* 00072 @brief Declare a function suitable for use with irplib_dfs_table_convert() 00073 @param table_set_row The name of the function to declare 00074 @see irplib_dfs_table_convert(), irplib_table_read_from_frameset() 00075 00076 */ 00077 /*----------------------------------------------------------------------------*/ 00078 #define IRPLIB_UTIL_SET_ROW(table_set_row) \ 00079 cpl_boolean table_set_row(cpl_table *, \ 00080 const char *, \ 00081 int, \ 00082 const cpl_frame *, \ 00083 const cpl_parameterlist *) 00084 00085 00086 /*----------------------------------------------------------------------------*/ 00087 /* 00088 @brief Declare a function suitable for use with irplib_dfs_table_convert() 00089 @param table_check The name of the function to declare 00090 @see irplib_dfs_table_convert() 00091 00092 */ 00093 /*----------------------------------------------------------------------------*/ 00094 #define IRPLIB_UTIL_CHECK(table_check) \ 00095 cpl_error_code table_check(cpl_table *, \ 00096 const cpl_frameset *, \ 00097 const cpl_parameterlist *) 00098 00099 00100 /*----------------------------------------------------------------------------*/ 00101 /* 00102 @brief Conditional skip to the (unqiue) return point of the function 00103 @param CONDITION The condition to check 00104 @see cpl_error_ensure() 00105 00106 skip_if() takes one argument, which is a logical expression. 00107 If the logical expression is false skip_if() takes no action and 00108 program execution continues. 00109 If the logical expression is true this indicates an error. In this case 00110 skip_if() will set the location of the error to the point where it 00111 was invoked in the recipe code (unless the error location is already in the 00112 recipe code). If no error code had been set, then skip_if() will set one. 00113 Finally, skip_if() causes program execution to skip to the macro 'end_skip'. 00114 The macro end_skip is located towards the end of the function, after 00115 which all resource deallocation and the function return is located. 00116 00117 The use of skip_if() assumes the following coding practice: 00118 1) Pointers used for dynamically allocated memory that they "own" shall always 00119 point to either NULL or to allocated memory (including CPL-objects). 00120 2) Such pointers may not be reused to point to memory whose deallocation 00121 requires calls to different functions. 00122 3) Pointers of type FILE should be set NULL when not pointing to an open 00123 stream and their closing calls (fclose(), freopen(), etc.) following the 00124 'end_skip' should be guarded against such NULL pointers. 00125 00126 Error checking with skip_if() is encouraged due to the following advantages: 00127 1) It ensures that a CPL-error code is set. 00128 2) It ensures that the location of the error in the _recipe_ code is noted. 00129 3) The error checking may be confined to a single concise line. 00130 4) It is not necessary to replicate memory deallocation for every error 00131 condition. 00132 5) If more extensive error reporting/handling is required it is not precluded 00133 by the use of skip_if(). 00134 6) It allows for a single point of function return. 00135 7) It allows for optional, uniformly formatted debugging/tracing information 00136 at each macro invocation. 00137 00138 The implementation of skip_if() uses a goto/label construction. 00139 According to Kerningham & Ritchie, The C Programming Language, 2nd edition, 00140 Section 3.8: 00141 "This organization is handy if the error-handling code is non-trivial, 00142 and if errors can occur in several places." 00143 00144 The use of goto for any other purpose should be avoided. 00145 00146 */ 00147 /*----------------------------------------------------------------------------*/ 00148 #define skip_if(CONDITION) \ 00149 do { \ 00150 cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), \ 00151 goto cleanup, "Propagating a pre-existing error"); \ 00152 cpl_error_ensure(!(CONDITION), cpl_error_get_code(), \ 00153 goto cleanup, "Propagating error");\ 00154 } while (0) 00155 00156 /*----------------------------------------------------------------------------*/ 00157 /* 00158 @brief Skip if A < B 00159 @param A The 1st double to compare 00160 @param B The 2nd double to compare 00161 @param MSG The message to use on failure 00162 @see skip_if() 00163 @note A and B are evaluated exactly once 00164 */ 00165 /*----------------------------------------------------------------------------*/ 00166 #define skip_if_lt(A, B, MSG) \ 00167 do { \ 00168 const double tmpa = (double)(A); \ 00169 const double tmpb = (double)(B); \ 00170 \ 00171 cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), \ 00172 goto cleanup, "Propagating a pre-existing error"); \ 00173 cpl_error_ensure(tmpa >= tmpb, CPL_ERROR_DATA_NOT_FOUND, \ 00174 goto cleanup, "Need at least %g (not %g) %s", \ 00175 tmpb, tmpa, MSG); \ 00176 } while (0) 00177 00178 /*----------------------------------------------------------------------------*/ 00179 /* 00180 @brief Conditional skip on coding bug 00181 @param CONDITION The condition to check 00182 @see skip_if() 00183 @note unlike assert() this check cannot be disabled 00184 */ 00185 /*----------------------------------------------------------------------------*/ 00186 #define bug_if(CONDITION) \ 00187 do { \ 00188 cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), \ 00189 goto cleanup, "Propagating an unexpected error, " \ 00190 "please report to " PACKAGE_BUGREPORT); \ 00191 cpl_error_ensure(!(CONDITION), CPL_ERROR_UNSPECIFIED, \ 00192 goto cleanup, "Internal error, please report to " \ 00193 PACKAGE_BUGREPORT); \ 00194 } while (0) 00195 00196 /*----------------------------------------------------------------------------*/ 00197 /* 00198 @brief Conditional skip with error creation 00199 @param CONDITION The condition to check 00200 @param ERROR The error code to set 00201 @param MSG A printf-style error message. As a matter of 00202 user-friendliness the message should mention any 00203 value that caused the @em CONDITION to fail. 00204 @see skip_if() 00205 @note unlike assert() this check cannot be disabled 00206 */ 00207 /*----------------------------------------------------------------------------*/ 00208 #define error_if(CONDITION, ERROR, ...) \ 00209 do { \ 00210 cpl_error_ensure(cpl_error_get_code() == CPL_ERROR_NONE && \ 00211 !(CONDITION), ERROR, goto cleanup, __VA_ARGS__); \ 00212 } while (0) 00213 00214 /*----------------------------------------------------------------------------*/ 00215 /* 00216 @brief Define the single point of resource deallocation and return 00217 @see skip_if() 00218 @note end_skip should be used exactly once in functions that use skip_if() etc 00219 */ 00220 /*----------------------------------------------------------------------------*/ 00221 #define end_skip \ 00222 do { \ 00223 cleanup: \ 00224 if (cpl_error_get_code()) \ 00225 cpl_msg_debug(cpl_func, "Cleanup in " __FILE__ " line %u with " \ 00226 "error '%s' at %s", __LINE__, \ 00227 cpl_error_get_message(), cpl_error_get_where()); \ 00228 else \ 00229 cpl_msg_debug(cpl_func, "Cleanup in " __FILE__ " line %u", \ 00230 __LINE__); \ 00231 } while (0) 00232 00233 00234 /*----------------------------------------------------------------------------*/ 00246 /*----------------------------------------------------------------------------*/ 00247 #define irplib_ensure(CONDITION, ec, ...) \ 00248 cpl_error_ensure(CONDITION, ec, goto cleanup, __VA_ARGS__) 00249 00250 /*----------------------------------------------------------------------------*/ 00280 /*----------------------------------------------------------------------------*/ 00281 00282 #define irplib_check(COMMAND, ...) \ 00283 do { \ 00284 cpl_errorstate irplib_check_prestate = cpl_errorstate_get(); \ 00285 skip_if(0); \ 00286 COMMAND; \ 00287 irplib_trace(); \ 00288 irplib_ensure(cpl_errorstate_is_equal(irplib_check_prestate), \ 00289 cpl_error_get_code(), __VA_ARGS__); \ 00290 irplib_trace(); \ 00291 } while (0) 00292 00293 /*----------------------------------------------------------------------------- 00294 Function prototypes 00295 -----------------------------------------------------------------------------*/ 00296 00297 void irplib_reset(void); 00298 int irplib_compare_tags(cpl_frame *, cpl_frame *); 00299 const char * irplib_frameset_find_file(const cpl_frameset *, const char *); 00300 cpl_frame * irplib_frameset_get_first_from_group(const cpl_frameset *, 00301 cpl_frame_group); 00302 00303 cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures *, int *, 00304 int); 00305 00306 int irplib_isinf(double value); 00307 int irplib_isnan(double value); 00308 00309 void irplib_errorstate_warning(unsigned, unsigned, unsigned); 00310 00311 cpl_error_code 00312 irplib_dfs_table_convert(cpl_table *, cpl_frameset *, const cpl_frameset *, 00313 int, char, const char *, const char *, 00314 const cpl_parameterlist *, const char *, 00315 const cpl_propertylist *, const cpl_propertylist *, 00316 const char *, const char *, const char *, 00317 cpl_boolean (*)(cpl_table *, const char *, int, 00318 const cpl_frame *, 00319 const cpl_parameterlist *), 00320 cpl_error_code (*)(cpl_table *, 00321 const cpl_frameset *, 00322 const cpl_parameterlist *)); 00323 00324 cpl_error_code irplib_table_read_from_frameset(cpl_table *, 00325 const cpl_frameset *, 00326 int, 00327 char, 00328 const cpl_parameterlist *, 00329 cpl_boolean (*) 00330 (cpl_table *, const char *, 00331 int, const cpl_frame *, 00332 const cpl_parameterlist *)); 00333 00334 cpl_error_code irplib_image_split(const cpl_image *, 00335 cpl_image *, cpl_image *, cpl_image *, 00336 double, cpl_boolean, 00337 double, cpl_boolean, 00338 double, double, 00339 cpl_boolean, cpl_boolean, cpl_boolean); 00340 00341 #endif
1.5.1