Wed Oct 28 11:45:43 2009

Asterisk developer's documentation


utils.h

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  * \brief Utility functions
00021  */
00022 
00023 #ifndef _ASTERISK_UTILS_H
00024 #define _ASTERISK_UTILS_H
00025 
00026 #include "asterisk/network.h"
00027 
00028 #include <time.h> /* we want to override localtime_r */
00029 #include <unistd.h>
00030 
00031 #include "asterisk/lock.h"
00032 #include "asterisk/time.h"
00033 #include "asterisk/logger.h"
00034 #include "asterisk/localtime.h"
00035 
00036 /*! 
00037 \note \verbatim
00038    Note:
00039    It is very important to use only unsigned variables to hold
00040    bit flags, as otherwise you can fall prey to the compiler's
00041    sign-extension antics if you try to use the top two bits in
00042    your variable.
00043 
00044    The flag macros below use a set of compiler tricks to verify
00045    that the caller is using an "unsigned int" variable to hold
00046    the flags, and nothing else. If the caller uses any other
00047    type of variable, a warning message similar to this:
00048 
00049    warning: comparison of distinct pointer types lacks cast
00050    will be generated.
00051 
00052    The "dummy" variable below is used to make these comparisons.
00053 
00054    Also note that at -O2 or above, this type-safety checking
00055    does _not_ produce any additional object code at all.
00056  \endverbatim
00057 */
00058 
00059 extern unsigned int __unsigned_int_flags_dummy;
00060 
00061 #define ast_test_flag(p,flag)       ({ \
00062                typeof ((p)->flags) __p = (p)->flags; \
00063                typeof (__unsigned_int_flags_dummy) __x = 0; \
00064                (void) (&__p == &__x); \
00065                ((p)->flags & (flag)); \
00066                })
00067 
00068 #define ast_set_flag(p,flag)     do { \
00069                typeof ((p)->flags) __p = (p)->flags; \
00070                typeof (__unsigned_int_flags_dummy) __x = 0; \
00071                (void) (&__p == &__x); \
00072                ((p)->flags |= (flag)); \
00073                } while(0)
00074 
00075 #define ast_clear_flag(p,flag)      do { \
00076                typeof ((p)->flags) __p = (p)->flags; \
00077                typeof (__unsigned_int_flags_dummy) __x = 0; \
00078                (void) (&__p == &__x); \
00079                ((p)->flags &= ~(flag)); \
00080                } while(0)
00081 
00082 #define ast_copy_flags(dest,src,flagz) do { \
00083                typeof ((dest)->flags) __d = (dest)->flags; \
00084                typeof ((src)->flags) __s = (src)->flags; \
00085                typeof (__unsigned_int_flags_dummy) __x = 0; \
00086                (void) (&__d == &__x); \
00087                (void) (&__s == &__x); \
00088                (dest)->flags &= ~(flagz); \
00089                (dest)->flags |= ((src)->flags & (flagz)); \
00090                } while (0)
00091 
00092 #define ast_set2_flag(p,value,flag) do { \
00093                typeof ((p)->flags) __p = (p)->flags; \
00094                typeof (__unsigned_int_flags_dummy) __x = 0; \
00095                (void) (&__p == &__x); \
00096                if (value) \
00097                   (p)->flags |= (flag); \
00098                else \
00099                   (p)->flags &= ~(flag); \
00100                } while (0)
00101 
00102 #define ast_set_flags_to(p,flag,value) do { \
00103                typeof ((p)->flags) __p = (p)->flags; \
00104                typeof (__unsigned_int_flags_dummy) __x = 0; \
00105                (void) (&__p == &__x); \
00106                (p)->flags &= ~(flag); \
00107                (p)->flags |= (value); \
00108                } while (0)
00109 
00110 
00111 /* The following 64-bit flag code can most likely be erased after app_dial
00112    is reorganized to either reduce the large number of options, or handle
00113    them in some other way. At the time of this writing, app_dial would be
00114    the only user of 64-bit option flags */
00115 
00116 extern uint64_t __unsigned_int_flags_dummy64;
00117 
00118 #define ast_test_flag64(p,flag)     ({ \
00119                typeof ((p)->flags) __p = (p)->flags; \
00120                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00121                (void) (&__p == &__x); \
00122                ((p)->flags & (flag)); \
00123                })
00124 
00125 #define ast_set_flag64(p,flag)      do { \
00126                typeof ((p)->flags) __p = (p)->flags; \
00127                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00128                (void) (&__p == &__x); \
00129                ((p)->flags |= (flag)); \
00130                } while(0)
00131 
00132 #define ast_clear_flag64(p,flag)       do { \
00133                typeof ((p)->flags) __p = (p)->flags; \
00134                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00135                (void) (&__p == &__x); \
00136                ((p)->flags &= ~(flag)); \
00137                } while(0)
00138 
00139 #define ast_copy_flags64(dest,src,flagz)  do { \
00140                typeof ((dest)->flags) __d = (dest)->flags; \
00141                typeof ((src)->flags) __s = (src)->flags; \
00142                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00143                (void) (&__d == &__x); \
00144                (void) (&__s == &__x); \
00145                (dest)->flags &= ~(flagz); \
00146                (dest)->flags |= ((src)->flags & (flagz)); \
00147                } while (0)
00148 
00149 #define ast_set2_flag64(p,value,flag)  do { \
00150                typeof ((p)->flags) __p = (p)->flags; \
00151                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00152                (void) (&__p == &__x); \
00153                if (value) \
00154                   (p)->flags |= (flag); \
00155                else \
00156                   (p)->flags &= ~(flag); \
00157                } while (0)
00158 
00159 #define ast_set_flags_to64(p,flag,value)  do { \
00160                typeof ((p)->flags) __p = (p)->flags; \
00161                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00162                (void) (&__p == &__x); \
00163                (p)->flags &= ~(flag); \
00164                (p)->flags |= (value); \
00165                } while (0)
00166 
00167 
00168 /* Non-type checking variations for non-unsigned int flags.  You
00169    should only use non-unsigned int flags where required by 
00170    protocol etc and if you know what you're doing :)  */
00171 #define ast_test_flag_nonstd(p,flag) \
00172                ((p)->flags & (flag))
00173 
00174 #define ast_set_flag_nonstd(p,flag)       do { \
00175                ((p)->flags |= (flag)); \
00176                } while(0)
00177 
00178 #define ast_clear_flag_nonstd(p,flag)     do { \
00179                ((p)->flags &= ~(flag)); \
00180                } while(0)
00181 
00182 #define ast_copy_flags_nonstd(dest,src,flagz)   do { \
00183                (dest)->flags &= ~(flagz); \
00184                (dest)->flags |= ((src)->flags & (flagz)); \
00185                } while (0)
00186 
00187 #define ast_set2_flag_nonstd(p,value,flag)   do { \
00188                if (value) \
00189                   (p)->flags |= (flag); \
00190                else \
00191                   (p)->flags &= ~(flag); \
00192                } while (0)
00193 
00194 #define AST_FLAGS_ALL UINT_MAX
00195 
00196 /*! \brief Structure used to handle boolean flags 
00197 */
00198 struct ast_flags {
00199    unsigned int flags;
00200 };
00201 
00202 /*! \brief Structure used to handle a large number of boolean flags == used only in app_dial?
00203 */
00204 struct ast_flags64 {
00205    uint64_t flags;
00206 };
00207 
00208 struct ast_hostent {
00209    struct hostent hp;
00210    char buf[1024];
00211 };
00212 
00213 /*! \brief Thread-safe gethostbyname function to use in Asterisk */
00214 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp);
00215 
00216 /*!  \brief Produces MD5 hash based on input string */
00217 void ast_md5_hash(char *output, char *input);
00218 /*! \brief Produces SHA1 hash based on input string */
00219 void ast_sha1_hash(char *output, char *input);
00220 
00221 int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks);
00222 
00223 /*!
00224  * \brief Encode data in base64
00225  * \param dst the destination buffer
00226  * \param src the source data to be encoded
00227  * \param srclen the number of bytes present in the source buffer
00228  * \param max the maximum number of bytes to write into the destination
00229  *        buffer, *including* the terminating NULL character.
00230  */
00231 int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max);
00232 
00233 /*!
00234  * \brief Decode data from base64
00235  * \param dst the destination buffer
00236  * \param src the source buffer
00237  * \param max The maximum number of bytes to write into the destination
00238  *            buffer.  Note that this function will not ensure that the
00239  *            destination buffer is NULL terminated.  So, in general,
00240  *            this parameter should be sizeof(dst) - 1.
00241  */
00242 int ast_base64decode(unsigned char *dst, const char *src, int max);
00243 
00244 /*!  \brief Turn text string to URI-encoded %XX version 
00245 
00246 \note    At this point, we're converting from ISO-8859-x (8-bit), not UTF8
00247    as in the SIP protocol spec 
00248    If doreserved == 1 we will convert reserved characters also.
00249    RFC 2396, section 2.4
00250    outbuf needs to have more memory allocated than the instring
00251    to have room for the expansion. Every char that is converted
00252    is replaced by three ASCII characters.
00253    \param string  String to be converted
00254    \param outbuf  Resulting encoded string
00255    \param buflen  Size of output buffer
00256    \param doreserved Convert reserved characters
00257 */
00258 
00259 char *ast_uri_encode(const char *string, char *outbuf, int buflen, int doreserved);
00260 
00261 /*!   \brief Decode URI, URN, URL (overwrite string)
00262    \param s String to be decoded 
00263  */
00264 void ast_uri_decode(char *s);
00265 
00266 static force_inline void ast_slinear_saturated_add(short *input, short *value)
00267 {
00268    int res;
00269 
00270    res = (int) *input + *value;
00271    if (res > 32767)
00272       *input = 32767;
00273    else if (res < -32767)
00274       *input = -32767;
00275    else
00276       *input = (short) res;
00277 }
00278 
00279 static force_inline void ast_slinear_saturated_subtract(short *input, short *value)
00280 {
00281    int res;
00282 
00283    res = (int) *input - *value;
00284    if (res > 32767)
00285       *input = 32767;
00286    else if (res < -32767)
00287       *input = -32767;
00288    else
00289       *input = (short) res;
00290 }
00291    
00292 static force_inline void ast_slinear_saturated_multiply(short *input, short *value)
00293 {
00294    int res;
00295 
00296    res = (int) *input * *value;
00297    if (res > 32767)
00298       *input = 32767;
00299    else if (res < -32767)
00300       *input = -32767;
00301    else
00302       *input = (short) res;
00303 }
00304 
00305 static force_inline void ast_slinear_saturated_divide(short *input, short *value)
00306 {
00307    *input /= *value;
00308 }
00309 
00310 #ifdef localtime_r
00311 #undef localtime_r
00312 #endif
00313 #define localtime_r __dont_use_localtime_r_use_ast_localtime_instead__
00314 
00315 int ast_utils_init(void);
00316 int ast_wait_for_input(int fd, int ms);
00317 
00318 /*!
00319    \brief Try to write string, but wait no more than ms milliseconds
00320    before timing out.
00321 
00322    \note If you are calling ast_carefulwrite, it is assumed that you are calling
00323    it on a file descriptor that _DOES_ have NONBLOCK set.  This way,
00324    there is only one system call made to do a write, unless we actually
00325    have a need to wait.  This way, we get better performance.
00326 */
00327 int ast_carefulwrite(int fd, char *s, int len, int timeoutms);
00328 
00329 /*!
00330  * \brief Write data to a file stream with a timeout
00331  *
00332  * \param f the file stream to write to
00333  * \param fd the file description to poll on to know when the file stream can
00334  *        be written to without blocking.
00335  * \param s the buffer to write from
00336  * \param len the number of bytes to write
00337  * \param timeoutms The maximum amount of time to block in this function trying
00338  *        to write, specified in milliseconds.
00339  *
00340  * \note This function assumes that the associated file stream has been set up
00341  *       as non-blocking.
00342  *
00343  * \retval 0 success
00344  * \retval -1 error
00345  */
00346 int ast_careful_fwrite(FILE *f, int fd, const char *s, size_t len, int timeoutms);
00347 
00348 /*
00349  * Thread management support (should be moved to lock.h or a different header)
00350  */
00351 
00352 #define AST_STACKSIZE (((sizeof(void *) * 8 * 8) - 16) * 1024)
00353 
00354 #if defined(LOW_MEMORY)
00355 #define AST_BACKGROUND_STACKSIZE (((sizeof(void *) * 8 * 2) - 16) * 1024)
00356 #else
00357 #define AST_BACKGROUND_STACKSIZE AST_STACKSIZE
00358 #endif
00359 
00360 void ast_register_thread(char *name);
00361 void ast_unregister_thread(void *id);
00362 
00363 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
00364               void *data, size_t stacksize, const char *file, const char *caller,
00365               int line, const char *start_fn);
00366 
00367 int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void*(*start_routine)(void *),
00368              void *data, size_t stacksize, const char *file, const char *caller,
00369              int line, const char *start_fn);
00370 
00371 #define ast_pthread_create(a, b, c, d)             \
00372    ast_pthread_create_stack(a, b, c, d,         \
00373       0, __FILE__, __FUNCTION__, __LINE__, #c)
00374 
00375 #define ast_pthread_create_detached(a, b, c, d)       \
00376    ast_pthread_create_detached_stack(a, b, c, d,      \
00377       0, __FILE__, __FUNCTION__, __LINE__, #c)
00378 
00379 #define ast_pthread_create_background(a, b, c, d)     \
00380    ast_pthread_create_stack(a, b, c, d,         \
00381       AST_BACKGROUND_STACKSIZE,        \
00382       __FILE__, __FUNCTION__, __LINE__, #c)
00383 
00384 #define ast_pthread_create_detached_background(a, b, c, d)  \
00385    ast_pthread_create_detached_stack(a, b, c, d,      \
00386       AST_BACKGROUND_STACKSIZE,        \
00387       __FILE__, __FUNCTION__, __LINE__, #c)
00388 
00389 /* End of thread management support */
00390 
00391 /*!
00392    \brief Process a string to find and replace characters
00393    \param start The string to analyze
00394    \param find The character to find
00395    \param replace_with The character that will replace the one we are looking for
00396 */
00397 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with);
00398 
00399 long int ast_random(void);
00400 
00401 
00402 /*! 
00403  * \brief free() wrapper
00404  *
00405  * ast_free_ptr should be used when a function pointer for free() needs to be passed
00406  * as the argument to a function. Otherwise, astmm will cause seg faults.
00407  */
00408 #ifdef __AST_DEBUG_MALLOC
00409 static void ast_free_ptr(void *ptr) attribute_unused;
00410 static void ast_free_ptr(void *ptr)
00411 {
00412    ast_free(ptr);
00413 }
00414 #else
00415 #define ast_free free
00416 #define ast_free_ptr ast_free
00417 #endif
00418 
00419 #ifndef __AST_DEBUG_MALLOC
00420 
00421 #define MALLOC_FAILURE_MSG \
00422    ast_log(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file);
00423 /*!
00424  * \brief A wrapper for malloc()
00425  *
00426  * ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
00427  * message in the case that the allocation fails.
00428  *
00429  * The argument and return value are the same as malloc()
00430  */
00431 #define ast_malloc(len) \
00432    _ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00433 
00434 AST_INLINE_API(
00435 void * attribute_malloc _ast_malloc(size_t len, const char *file, int lineno, const char *func),
00436 {
00437    void *p;
00438 
00439    if (!(p = malloc(len)))
00440       MALLOC_FAILURE_MSG;
00441 
00442    return p;
00443 }
00444 )
00445 
00446 /*!
00447  * \brief A wrapper for calloc()
00448  *
00449  * ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
00450  * message in the case that the allocation fails.
00451  *
00452  * The arguments and return value are the same as calloc()
00453  */
00454 #define ast_calloc(num, len) \
00455    _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00456 
00457 AST_INLINE_API(
00458 void * attribute_malloc _ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
00459 {
00460    void *p;
00461 
00462    if (!(p = calloc(num, len)))
00463       MALLOC_FAILURE_MSG;
00464 
00465    return p;
00466 }
00467 )
00468 
00469 /*!
00470  * \brief A wrapper for calloc() for use in cache pools
00471  *
00472  * ast_calloc_cache() is a wrapper for calloc() that will generate an Asterisk log
00473  * message in the case that the allocation fails. When memory debugging is in use,
00474  * the memory allocated by this function will be marked as 'cache' so it can be
00475  * distinguished from normal memory allocations.
00476  *
00477  * The arguments and return value are the same as calloc()
00478  */
00479 #define ast_calloc_cache(num, len) \
00480    _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00481 
00482 /*!
00483  * \brief A wrapper for realloc()
00484  *
00485  * ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
00486  * message in the case that the allocation fails.
00487  *
00488  * The arguments and return value are the same as realloc()
00489  */
00490 #define ast_realloc(p, len) \
00491    _ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00492 
00493 AST_INLINE_API(
00494 void * attribute_malloc _ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
00495 {
00496    void *newp;
00497 
00498    if (!(newp = realloc(p, len)))
00499       MALLOC_FAILURE_MSG;
00500 
00501    return newp;
00502 }
00503 )
00504 
00505 /*!
00506  * \brief A wrapper for strdup()
00507  *
00508  * ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
00509  * message in the case that the allocation fails.
00510  *
00511  * ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
00512  * argument is provided, ast_strdup will return NULL without generating any
00513  * kind of error log message.
00514  *
00515  * The argument and return value are the same as strdup()
00516  */
00517 #define ast_strdup(str) \
00518    _ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00519 
00520 AST_INLINE_API(
00521 char * attribute_malloc _ast_strdup(const char *str, const char *file, int lineno, const char *func),
00522 {
00523    char *newstr = NULL;
00524 
00525    if (str) {
00526       if (!(newstr = strdup(str)))
00527          MALLOC_FAILURE_MSG;
00528    }
00529 
00530    return newstr;
00531 }
00532 )
00533 
00534 /*!
00535  * \brief A wrapper for strndup()
00536  *
00537  * ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
00538  * message in the case that the allocation fails.
00539  *
00540  * ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
00541  * string to duplicate. If a NULL argument is provided, ast_strdup will return  
00542  * NULL without generating any kind of error log message.
00543  *
00544  * The arguments and return value are the same as strndup()
00545  */
00546 #define ast_strndup(str, len) \
00547    _ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00548 
00549 AST_INLINE_API(
00550 char * attribute_malloc _ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
00551 {
00552    char *newstr = NULL;
00553 
00554    if (str) {
00555       if (!(newstr = strndup(str, len)))
00556          MALLOC_FAILURE_MSG;
00557    }
00558 
00559    return newstr;
00560 }
00561 )
00562 
00563 /*!
00564  * \brief A wrapper for asprintf()
00565  *
00566  * ast_asprintf() is a wrapper for asprintf() that will generate an Asterisk log
00567  * message in the case that the allocation fails.
00568  *
00569  * The arguments and return value are the same as asprintf()
00570  */
00571 #define ast_asprintf(ret, fmt, ...) \
00572    _ast_asprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, __VA_ARGS__)
00573 
00574 int __attribute__((format(printf, 5, 6)))
00575    _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...);
00576 
00577 /*!
00578  * \brief A wrapper for vasprintf()
00579  *
00580  * ast_vasprintf() is a wrapper for vasprintf() that will generate an Asterisk log
00581  * message in the case that the allocation fails.
00582  *
00583  * The arguments and return value are the same as vasprintf()
00584  */
00585 #define ast_vasprintf(ret, fmt, ap) \
00586    _ast_vasprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, (fmt), (ap))
00587 
00588 AST_INLINE_API(
00589 __attribute__((format(printf, 5, 0)))
00590 int _ast_vasprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, va_list ap),
00591 {
00592    int res;
00593 
00594    if ((res = vasprintf(ret, fmt, ap)) == -1)
00595       MALLOC_FAILURE_MSG;
00596 
00597    return res;
00598 }
00599 )
00600 
00601 #endif /* AST_DEBUG_MALLOC */
00602 
00603 #if !defined(ast_strdupa) && defined(__GNUC__)
00604 /*!
00605   \brief duplicate a string in memory from the stack
00606   \param s The string to duplicate
00607 
00608   This macro will duplicate the given string.  It returns a pointer to the stack
00609   allocatted memory for the new string.
00610 */
00611 #define ast_strdupa(s)                                                    \
00612    (__extension__                                                    \
00613    ({                                                                \
00614       const char *__old = (s);                                  \
00615       size_t __len = strlen(__old) + 1;                         \
00616       char *__new = __builtin_alloca(__len);                    \
00617       memcpy (__new, __old, __len);                             \
00618       __new;                                                    \
00619    }))
00620 #endif
00621 
00622 /*!
00623   \brief Disable PMTU discovery on a socket
00624   \param sock The socket to manipulate
00625   \return Nothing
00626 
00627   On Linux, UDP sockets default to sending packets with the Dont Fragment (DF)
00628   bit set. This is supposedly done to allow the application to do PMTU
00629   discovery, but Asterisk does not do this.
00630 
00631   Because of this, UDP packets sent by Asterisk that are larger than the MTU
00632   of any hop in the path will be lost. This function can be called on a socket
00633   to ensure that the DF bit will not be set.
00634  */
00635 void ast_enable_packet_fragmentation(int sock);
00636 
00637 /*!
00638   \brief Recursively create directory path
00639   \param path The directory path to create
00640   \param mode The permissions with which to try to create the directory
00641   \return 0 on success or an error code otherwise
00642 
00643   Creates a directory path, creating parent directories as needed.
00644  */
00645 int ast_mkdir(const char *path, int mode);
00646 
00647 #define ARRAY_LEN(a) (sizeof(a) / sizeof(0[a]))
00648 
00649 #ifdef AST_DEVMODE
00650 #define ast_assert(a) _ast_assert(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00651 static void force_inline _ast_assert(int condition, const char *condition_str, 
00652    const char *file, int line, const char *function)
00653 {
00654    if (__builtin_expect(!condition, 1)) {
00655       /* Attempt to put it into the logger, but hope that at least someone saw the
00656        * message on stderr ... */
00657       ast_log(__LOG_ERROR, file, line, function, "FRACK!, Failed assertion %s (%d)\n",
00658          condition_str, condition);
00659       fprintf(stderr, "FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
00660          condition_str, condition, line, function, file);
00661       /* Give the logger a chance to get the message out, just in case we abort(), or
00662        * Asterisk crashes due to whatever problem just happened after we exit ast_assert(). */
00663       usleep(1);
00664 #ifdef DO_CRASH
00665       abort();
00666       /* Just in case abort() doesn't work or something else super silly,
00667        * and for Qwell's amusement. */
00668       *((int*)0)=0;
00669 #endif
00670    }
00671 }
00672 #else
00673 #define ast_assert(a)
00674 #endif
00675 
00676 #include "asterisk/strings.h"
00677 
00678 #endif /* _ASTERISK_UTILS_H */

Generated on Wed Oct 28 11:45:43 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6