irplib_utils.h

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

Generated on Thu Nov 15 14:32:26 2007 for UVES Pipeline Reference Manual by  doxygen 1.5.1