GIRAFFE Pipeline Reference Manual

irplib_utils.h

00001 /* $Id: irplib_utils.h,v 1.2.2.1 2008/06/10 14:09:33 rpalsa 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: rpalsa $
00023  * $Date: 2008/06/10 14:09:33 $
00024  * $Revision: 1.2.2.1 $
00025  * $Name: giraffe-2_5_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   @brief   Conditional skip to the (unqiue) return point of the function
00072   @param   CONDITION    The condition to check
00073   @see cpl_error_ensure()
00074 
00075   skip_if() takes one argument, which is a logical expression. 
00076   If the logical expression is false skip_if() takes no action and
00077   program execution continues.
00078   If the logical expression is true this indicates an error. In this case
00079   skip_if() will set the location of the error to the point where it
00080   was invoked in the recipe code (unless the error location is already in the
00081   recipe code). If no error code had been set, then skip_if() will set one.
00082   Finally, skip_if() causes program execution to skip to the macro 'end_skip'.
00083   The macro end_skip is located towards the end of the function, after
00084   which all resource deallocation and the function return is located. 
00085 
00086   The use of skip_if() assumes the following coding practice:
00087   1) Pointers used for dynamically allocated memory that they "own" shall always
00088      point to either NULL or to allocated memory (including CPL-objects).
00089   2) Such pointers may not be reused to point to memory whose deallocation
00090      requires calls to different functions.
00091   3) Pointers of type FILE should be set NULL when not pointing to an open
00092      stream and their closing calls (fclose(), freopen(), etc.) following the
00093      'end_skip' should be guarded against such NULL pointers.
00094 
00095   Error checking with skip_if() is encouraged due to the following advantages:
00096   1) It ensures that a CPL-error code is set.
00097   2) It ensures that the location of the error in the _recipe_ code is noted.
00098   3) The error checking may be confined to a single concise line.
00099   4) It is not necessary to replicate memory deallocation for every error
00100      condition.
00101   5) If more extensive error reporting/handling is required it is not precluded
00102      by the use of skip_if().
00103   6) It allows for a single point of function return.
00104   7) It allows for optional, uniformly formatted debugging/tracing information
00105      at each macro invocation.
00106 
00107   The implementation of skip_if() uses a goto/label construction.
00108   According to Kerningham & Ritchie, The C Programming Language, 2nd edition,
00109   Section 3.8:
00110   "This organization is handy if the error-handling code is non-trivial,
00111   and if errors can occur in several places."
00112 
00113   The use of goto for any other purpose should be avoided.
00114 
00115 */
00116 /*----------------------------------------------------------------------------*/
00117 #define skip_if(CONDITION)                                                     \
00118     do {                                                                       \
00119         cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(),          \
00120                          goto cleanup, "Propagating a pre-existing error");    \
00121         cpl_error_ensure(!(CONDITION), cpl_error_get_code(),                   \
00122                          goto cleanup, "Propagating error");\
00123     } while (0)
00124 
00125 /*----------------------------------------------------------------------------*/
00126 /*
00127   @brief   Skip if A < B
00128   @param   A   The 1st double to compare
00129   @param   B   The 2nd double to compare
00130   @param   MSG The message to use on failure
00131   @see skip_if()
00132   @note A and B are evaluated exactly once
00133 */
00134 /*----------------------------------------------------------------------------*/
00135 #define skip_if_lt(A, B, MSG)                                                  \
00136     do {                                                                       \
00137         const double tmpa = (double)(A);                                       \
00138         const double tmpb = (double)(B);                                       \
00139                                                                                \
00140         cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(),          \
00141                          goto cleanup, "Propagating a pre-existing error");    \
00142         cpl_error_ensure(tmpa >= tmpb, CPL_ERROR_DATA_NOT_FOUND,               \
00143                          goto cleanup, "Need at least %g (not %g) %s",         \
00144                          tmpb, tmpa, MSG);                                     \
00145     } while (0)
00146 
00147 /*----------------------------------------------------------------------------*/
00148 /*
00149   @brief   Conditional skip on coding bug
00150   @param   CONDITION    The condition to check
00151   @see skip_if()
00152   @note unlike assert() this check cannot be disabled
00153  */
00154 /*----------------------------------------------------------------------------*/
00155 #define bug_if(CONDITION)                                                      \
00156     do {                                                                       \
00157         cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(),          \
00158                          goto cleanup, "Propagating an unexpected error, "     \
00159                          "please report to " 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   Conditional skip with error creation
00168   @param   CONDITION    The condition to check
00169   @param   ERROR        The error code to set
00170   @param   MSG          A printf-style error message. As a matter of
00171                         user-friendliness the message should mention any
00172                         value that caused the @em CONDITION to fail.
00173   @see skip_if()
00174   @note unlike assert() this check cannot be disabled
00175  */
00176 /*----------------------------------------------------------------------------*/
00177 #define error_if(CONDITION, ERROR, ...)                                        \
00178     do {                                                                       \
00179         cpl_error_ensure(cpl_error_get_code() == CPL_ERROR_NONE &&             \
00180                          !(CONDITION), ERROR, goto cleanup,  __VA_ARGS__);     \
00181     } while (0)
00182 
00183 /*----------------------------------------------------------------------------*/
00184 /*
00185   @brief   Define the single point of resource deallocation and return
00186   @see skip_if()
00187   @note end_skip should be used exactly once in functions that use skip_if() etc
00188 */
00189 /*----------------------------------------------------------------------------*/
00190 #define end_skip \
00191     do {                                                                     \
00192         cleanup:                                                             \
00193         if (cpl_error_get_code())                                            \
00194             cpl_msg_debug(cpl_func, "Cleanup in " __FILE__ " line %u with "  \
00195                           "error '%s' at %s", __LINE__,                      \
00196                           cpl_error_get_message(), cpl_error_get_where());   \
00197         else                                                                 \
00198             cpl_msg_debug(cpl_func, "Cleanup in " __FILE__ " line %u",       \
00199                           __LINE__);                                         \
00200     } while (0)
00201 
00202 
00203 /*----------------------------------------------------------------------------*/
00215 /*----------------------------------------------------------------------------*/
00216 #define irplib_ensure(CONDITION, ec, ...)                                      \
00217     cpl_error_ensure(CONDITION, ec, goto cleanup,  __VA_ARGS__)
00218 
00219 /*----------------------------------------------------------------------------*/
00249 /*----------------------------------------------------------------------------*/
00250 
00251 #define irplib_check(COMMAND, ...)                                             \
00252   do {                                                                         \
00253     cpl_errorstate irplib_check_prestate = cpl_errorstate_get();               \
00254     skip_if(0);                                                                \
00255     COMMAND;                                                                   \
00256         irplib_trace(); \
00257     irplib_ensure(cpl_errorstate_is_equal(irplib_check_prestate),              \
00258                   cpl_error_get_code(), __VA_ARGS__);                          \
00259         irplib_trace(); \
00260   } while (0)
00261 
00262 /*-----------------------------------------------------------------------------
00263                                    Function prototypes
00264  -----------------------------------------------------------------------------*/
00265 
00266 void irplib_reset(void);
00267 int irplib_compare_tags(cpl_frame *, cpl_frame *);
00268 const char * irplib_frameset_find_file(const cpl_frameset *, const char *);
00269 cpl_frame * irplib_frameset_get_first_from_group(const cpl_frameset *,
00270                                                  cpl_frame_group);
00271 
00272 cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures *, int *,
00273                                               int);
00274 
00275 int irplib_isinf(double value);
00276 int irplib_isnan(double value);
00277 
00278 void irplib_errorstate_warning(unsigned, unsigned, unsigned);
00279 
00280 #endif

This file is part of the GIRAFFE Pipeline Reference Manual 2.5.2.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri Jun 13 14:36:26 2008 by doxygen 1.4.6 written by Dimitri van Heesch, © 1997-2004