Home | History | Annotate | Download | only in curl
      1 #ifndef __CURL_TYPECHECK_GCC_H
      2 #define __CURL_TYPECHECK_GCC_H
      3 /***************************************************************************
      4  *                                  _   _ ____  _
      5  *  Project                     ___| | | |  _ \| |
      6  *                             / __| | | | |_) | |
      7  *                            | (__| |_| |  _ <| |___
      8  *                             \___|\___/|_| \_\_____|
      9  *
     10  * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel (at) haxx.se>, et al.
     11  *
     12  * This software is licensed as described in the file COPYING, which
     13  * you should have received as part of this distribution. The terms
     14  * are also available at http://curl.haxx.se/docs/copyright.html.
     15  *
     16  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     17  * copies of the Software, and permit persons to whom the Software is
     18  * furnished to do so, under the terms of the COPYING file.
     19  *
     20  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     21  * KIND, either express or implied.
     22  *
     23  * $Id: typecheck-gcc.h,v 1.9 2009-01-25 23:26:31 bagder Exp $
     24  ***************************************************************************/
     25 
     26 /* wraps curl_easy_setopt() with typechecking */
     27 
     28 /* To add a new kind of warning, add an
     29  *   if(_curl_is_sometype_option(_curl_opt) && ! _curl_is_sometype(value))
     30  *     _curl_easy_setopt_err_sometype();
     31  * block and define _curl_is_sometype_option, _curl_is_sometype and
     32  * _curl_easy_setopt_err_sometype below
     33  *
     34  * To add an option that uses the same type as an existing option, you'll just
     35  * need to extend the appropriate _curl_*_option macro
     36  */
     37 #define curl_easy_setopt(handle, option, value)                               \
     38 __extension__ ({                                                              \
     39   __typeof__ (option) _curl_opt = option;                                     \
     40   if (__builtin_constant_p(_curl_opt)) {                                      \
     41     if (_curl_is_long_option(_curl_opt) && !_curl_is_long(value))             \
     42       _curl_easy_setopt_err_long();                                           \
     43     if (_curl_is_off_t_option(_curl_opt) && !_curl_is_off_t(value))           \
     44       _curl_easy_setopt_err_curl_off_t();                                     \
     45     if (_curl_is_string_option(_curl_opt) && !_curl_is_string(value))         \
     46       _curl_easy_setopt_err_string();                                         \
     47     if (_curl_is_write_cb_option(_curl_opt) && !_curl_is_write_cb(value))     \
     48       _curl_easy_setopt_err_write_callback();                                 \
     49     if ((_curl_opt) == CURLOPT_READFUNCTION && !_curl_is_read_cb(value))      \
     50       _curl_easy_setopt_err_read_cb();                                        \
     51     if ((_curl_opt) == CURLOPT_IOCTLFUNCTION && !_curl_is_ioctl_cb(value))    \
     52       _curl_easy_setopt_err_ioctl_cb();                                       \
     53     if ((_curl_opt) == CURLOPT_SOCKOPTFUNCTION && !_curl_is_sockopt_cb(value))\
     54       _curl_easy_setopt_err_sockopt_cb();                                     \
     55     if ((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION &&                          \
     56             !_curl_is_opensocket_cb(value))                                   \
     57       _curl_easy_setopt_err_opensocket_cb();                                  \
     58     if ((_curl_opt) == CURLOPT_PROGRESSFUNCTION &&                            \
     59             !_curl_is_progress_cb(value))                                     \
     60       _curl_easy_setopt_err_progress_cb();                                    \
     61     if ((_curl_opt) == CURLOPT_DEBUGFUNCTION && !_curl_is_debug_cb(value))    \
     62       _curl_easy_setopt_err_debug_cb();                                       \
     63     if ((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION &&                            \
     64             !_curl_is_ssl_ctx_cb(value))                                      \
     65       _curl_easy_setopt_err_ssl_ctx_cb();                                     \
     66     if (_curl_is_conv_cb_option(_curl_opt) && !_curl_is_conv_cb(value))       \
     67       _curl_easy_setopt_err_conv_cb();                                        \
     68     if ((_curl_opt) == CURLOPT_SEEKFUNCTION && !_curl_is_seek_cb(value))      \
     69       _curl_easy_setopt_err_seek_cb();                                        \
     70     if (_curl_is_cb_data_option(_curl_opt) && !_curl_is_cb_data(value))       \
     71       _curl_easy_setopt_err_cb_data();                                        \
     72     if ((_curl_opt) == CURLOPT_ERRORBUFFER && !_curl_is_error_buffer(value))  \
     73       _curl_easy_setopt_err_error_buffer();                                   \
     74     if ((_curl_opt) == CURLOPT_STDERR && !_curl_is_FILE(value))               \
     75       _curl_easy_setopt_err_FILE();                                           \
     76     if (_curl_is_postfields_option(_curl_opt) && !_curl_is_postfields(value)) \
     77       _curl_easy_setopt_err_postfields();                                     \
     78     if ((_curl_opt) == CURLOPT_HTTPPOST &&                                    \
     79             !_curl_is_arr((value), struct curl_httppost))                     \
     80       _curl_easy_setopt_err_curl_httpost();                                   \
     81     if (_curl_is_slist_option(_curl_opt) &&                                   \
     82             !_curl_is_arr((value), struct curl_slist))                        \
     83       _curl_easy_setopt_err_curl_slist();                                     \
     84     if ((_curl_opt) == CURLOPT_SHARE && !_curl_is_ptr((value), CURLSH))       \
     85       _curl_easy_setopt_err_CURLSH();                                         \
     86   }                                                                           \
     87   curl_easy_setopt(handle, _curl_opt, value);                                 \
     88 })
     89 
     90 /* wraps curl_easy_getinfo() with typechecking */
     91 /* FIXME: don't allow const pointers */
     92 #define curl_easy_getinfo(handle, info, arg)                                  \
     93 __extension__ ({                                                              \
     94   __typeof__ (info) _curl_info = info;                                        \
     95   if (__builtin_constant_p(_curl_info)) {                                     \
     96     if (_curl_is_string_info(_curl_info) && !_curl_is_arr((arg), char *))     \
     97       _curl_easy_getinfo_err_string();                                        \
     98     if (_curl_is_long_info(_curl_info) && !_curl_is_arr((arg), long))         \
     99       _curl_easy_getinfo_err_long();                                          \
    100     if (_curl_is_double_info(_curl_info) && !_curl_is_arr((arg), double))     \
    101       _curl_easy_getinfo_err_double();                                        \
    102     if (_curl_is_slist_info(_curl_info) &&                                    \
    103            !_curl_is_arr((arg), struct curl_slist *))                         \
    104       _curl_easy_getinfo_err_curl_slist();                                    \
    105   }                                                                           \
    106   curl_easy_getinfo(handle, _curl_info, arg);                                 \
    107 })
    108 
    109 /* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
    110  * for now just make sure that the functions are called with three
    111  * arguments
    112  */
    113 #define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
    114 #define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
    115 
    116 
    117 /* the actual warnings, triggered by calling the _curl_easy_setopt_err*
    118  * functions */
    119 
    120 /* To define a new warning, use _CURL_WARNING(identifier, "message") */
    121 #define _CURL_WARNING(id, message)                                            \
    122   static void __attribute__((warning(message))) __attribute__((unused))       \
    123   __attribute__((noinline)) id(void) { __asm__(""); }
    124 
    125 _CURL_WARNING(_curl_easy_setopt_err_long,
    126   "curl_easy_setopt expects a long argument for this option")
    127 _CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
    128   "curl_easy_setopt expects a curl_off_t argument for this option")
    129 _CURL_WARNING(_curl_easy_setopt_err_string,
    130   "curl_easy_setopt expects a string (char* or char[]) argument for this option"
    131   )
    132 _CURL_WARNING(_curl_easy_setopt_err_write_callback,
    133   "curl_easy_setopt expects a curl_write_callback argument for this option")
    134 _CURL_WARNING(_curl_easy_setopt_err_read_cb,
    135   "curl_easy_setopt expects a curl_read_callback argument for this option")
    136 _CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
    137   "curl_easy_setopt expects a curl_ioctl_callback argument for this option")
    138 _CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
    139   "curl_easy_setopt expects a curl_sockopt_callback argument for this option")
    140 _CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
    141   "curl_easy_setopt expects a curl_opensocket_callback argument for this option"
    142   )
    143 _CURL_WARNING(_curl_easy_setopt_err_progress_cb,
    144   "curl_easy_setopt expects a curl_progress_callback argument for this option")
    145 _CURL_WARNING(_curl_easy_setopt_err_debug_cb,
    146   "curl_easy_setopt expects a curl_debug_callback argument for this option")
    147 _CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
    148   "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
    149 _CURL_WARNING(_curl_easy_setopt_err_conv_cb,
    150   "curl_easy_setopt expects a curl_conv_callback argument for this option")
    151 _CURL_WARNING(_curl_easy_setopt_err_seek_cb,
    152   "curl_easy_setopt expects a curl_seek_callback argument for this option")
    153 _CURL_WARNING(_curl_easy_setopt_err_cb_data,
    154   "curl_easy_setopt expects a private data pointer as argument for this option")
    155 _CURL_WARNING(_curl_easy_setopt_err_error_buffer,
    156   "curl_easy_setopt expects a char buffer of CURL_ERROR_SIZE as argument for this option")
    157 _CURL_WARNING(_curl_easy_setopt_err_FILE,
    158   "curl_easy_setopt expects a FILE* argument for this option")
    159 _CURL_WARNING(_curl_easy_setopt_err_postfields,
    160   "curl_easy_setopt expects a void* or char* argument for this option")
    161 _CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
    162   "curl_easy_setopt expects a struct curl_httppost* argument for this option")
    163 _CURL_WARNING(_curl_easy_setopt_err_curl_slist,
    164   "curl_easy_setopt expects a struct curl_slist* argument for this option")
    165 _CURL_WARNING(_curl_easy_setopt_err_CURLSH,
    166   "curl_easy_setopt expects a CURLSH* argument for this option")
    167 
    168 _CURL_WARNING(_curl_easy_getinfo_err_string,
    169   "curl_easy_getinfo expects a pointer to char * for this info")
    170 _CURL_WARNING(_curl_easy_getinfo_err_long,
    171   "curl_easy_getinfo expects a pointer to long for this info")
    172 _CURL_WARNING(_curl_easy_getinfo_err_double,
    173   "curl_easy_getinfo expects a pointer to double for this info")
    174 _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
    175   "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
    176 
    177 /* groups of curl_easy_setops options that take the same type of argument */
    178 
    179 /* To add a new option to one of the groups, just add
    180  *   (option) == CURLOPT_SOMETHING
    181  * to the or-expression. If the option takes a long or curl_off_t, you don't
    182  * have to do anything
    183  */
    184 
    185 /* evaluates to true if option takes a long argument */
    186 #define _curl_is_long_option(option)                                          \
    187   (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
    188 
    189 #define _curl_is_off_t_option(option)                                         \
    190   ((option) > CURLOPTTYPE_OFF_T)
    191 
    192 /* evaluates to true if option takes a char* argument */
    193 #define _curl_is_string_option(option)                                        \
    194   ((option) == CURLOPT_URL ||                                                 \
    195    (option) == CURLOPT_PROXY ||                                               \
    196    (option) == CURLOPT_INTERFACE ||                                           \
    197    (option) == CURLOPT_NETRC_FILE ||                                          \
    198    (option) == CURLOPT_USERPWD ||                                             \
    199    (option) == CURLOPT_USERNAME ||                                            \
    200    (option) == CURLOPT_PASSWORD ||                                            \
    201    (option) == CURLOPT_PROXYUSERPWD ||                                        \
    202    (option) == CURLOPT_PROXYUSERNAME ||                                       \
    203    (option) == CURLOPT_PROXYPASSWORD ||                                       \
    204    (option) == CURLOPT_NOPROXY ||                                             \
    205    (option) == CURLOPT_ENCODING ||                                            \
    206    (option) == CURLOPT_REFERER ||                                             \
    207    (option) == CURLOPT_USERAGENT ||                                           \
    208    (option) == CURLOPT_COOKIE ||                                              \
    209    (option) == CURLOPT_COOKIEFILE ||                                          \
    210    (option) == CURLOPT_COOKIEJAR ||                                           \
    211    (option) == CURLOPT_COOKIELIST ||                                          \
    212    (option) == CURLOPT_FTPPORT ||                                             \
    213    (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER ||                             \
    214    (option) == CURLOPT_FTP_ACCOUNT ||                                         \
    215    (option) == CURLOPT_RANGE ||                                               \
    216    (option) == CURLOPT_CUSTOMREQUEST ||                                       \
    217    (option) == CURLOPT_SSLCERT ||                                             \
    218    (option) == CURLOPT_SSLCERTTYPE ||                                         \
    219    (option) == CURLOPT_SSLKEY ||                                              \
    220    (option) == CURLOPT_SSLKEYTYPE ||                                          \
    221    (option) == CURLOPT_KEYPASSWD ||                                           \
    222    (option) == CURLOPT_SSLENGINE ||                                           \
    223    (option) == CURLOPT_CAINFO ||                                              \
    224    (option) == CURLOPT_CAPATH ||                                              \
    225    (option) == CURLOPT_RANDOM_FILE ||                                         \
    226    (option) == CURLOPT_EGDSOCKET ||                                           \
    227    (option) == CURLOPT_SSL_CIPHER_LIST ||                                     \
    228    (option) == CURLOPT_KRBLEVEL ||                                            \
    229    (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 ||                             \
    230    (option) == CURLOPT_SSH_PUBLIC_KEYFILE ||                                  \
    231    (option) == CURLOPT_SSH_PRIVATE_KEYFILE ||                                 \
    232    (option) == CURLOPT_CRLFILE ||                                             \
    233    (option) == CURLOPT_ISSUERCERT ||                                          \
    234    0)
    235 
    236 /* evaluates to true if option takes a curl_write_callback argument */
    237 #define _curl_is_write_cb_option(option)                                      \
    238   ((option) == CURLOPT_HEADERFUNCTION ||                                      \
    239    (option) == CURLOPT_WRITEFUNCTION)
    240 
    241 /* evaluates to true if option takes a curl_conv_callback argument */
    242 #define _curl_is_conv_cb_option(option)                                       \
    243   ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION ||                            \
    244    (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION ||                          \
    245    (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
    246 
    247 /* evaluates to true if option takes a data argument to pass to a callback */
    248 #define _curl_is_cb_data_option(option)                                       \
    249   ((option) == CURLOPT_WRITEDATA ||                                           \
    250    (option) == CURLOPT_READDATA ||                                            \
    251    (option) == CURLOPT_IOCTLDATA ||                                           \
    252    (option) == CURLOPT_SOCKOPTDATA ||                                         \
    253    (option) == CURLOPT_OPENSOCKETDATA ||                                      \
    254    (option) == CURLOPT_PROGRESSDATA ||                                        \
    255    (option) == CURLOPT_WRITEHEADER ||                                         \
    256    (option) == CURLOPT_DEBUGDATA ||                                           \
    257    (option) == CURLOPT_SSL_CTX_DATA ||                                        \
    258    (option) == CURLOPT_SEEKDATA ||                                            \
    259    (option) == CURLOPT_PRIVATE ||                                             \
    260    0)
    261 
    262 /* evaluates to true if option takes a POST data argument (void* or char*) */
    263 #define _curl_is_postfields_option(option)                                    \
    264   ((option) == CURLOPT_POSTFIELDS ||                                          \
    265    (option) == CURLOPT_COPYPOSTFIELDS ||                                      \
    266    0)
    267 
    268 /* evaluates to true if option takes a struct curl_slist * argument */
    269 #define _curl_is_slist_option(option)                                         \
    270   ((option) == CURLOPT_HTTPHEADER ||                                          \
    271    (option) == CURLOPT_HTTP200ALIASES ||                                      \
    272    (option) == CURLOPT_QUOTE ||                                               \
    273    (option) == CURLOPT_POSTQUOTE ||                                           \
    274    (option) == CURLOPT_PREQUOTE ||                                            \
    275    (option) == CURLOPT_TELNETOPTIONS ||                                       \
    276    0)
    277 
    278 /* groups of curl_easy_getinfo infos that take the same type of argument */
    279 
    280 /* evaluates to true if info expects a pointer to char * argument */
    281 #define _curl_is_string_info(info)                                            \
    282   (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
    283 
    284 /* evaluates to true if info expects a pointer to long argument */
    285 #define _curl_is_long_info(info)                                              \
    286   (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
    287 
    288 /* evaluates to true if info expects a pointer to double argument */
    289 #define _curl_is_double_info(info)                                            \
    290   (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
    291 
    292 /* true if info expects a pointer to struct curl_slist * argument */
    293 #define _curl_is_slist_info(info)                                             \
    294   (CURLINFO_SLIST < (info))
    295 
    296 
    297 /* typecheck helpers -- check whether given expression has requested type*/
    298 
    299 /* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
    300  * otherwise define a new macro. Search for __builtin_types_compatible_p
    301  * in the GCC manual.
    302  * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
    303  * the actual expression passed to the curl_easy_setopt macro. This
    304  * means that you can only apply the sizeof and __typeof__ operators, no
    305  * == or whatsoever.
    306  */
    307 
    308 /* XXX: should evaluate to true iff expr is a pointer */
    309 #define _curl_is_any_ptr(expr)                                                \
    310   (sizeof(expr) == sizeof(void*))
    311 
    312 /* evaluates to true if expr is NULL */
    313 /* XXX: must not evaluate expr, so this check is not accurate */
    314 #define _curl_is_NULL(expr)                                                   \
    315   (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
    316 
    317 /* evaluates to true if expr is type*, const type* or NULL */
    318 #define _curl_is_ptr(expr, type)                                              \
    319   (_curl_is_NULL(expr) ||                                                     \
    320    __builtin_types_compatible_p(__typeof__(expr), type *) ||                  \
    321    __builtin_types_compatible_p(__typeof__(expr), const type *))
    322 
    323 /* evaluates to true if expr is one of type[], type*, NULL or const type* */
    324 #define _curl_is_arr(expr, type)                                              \
    325   (_curl_is_ptr((expr), type) ||                                              \
    326    __builtin_types_compatible_p(__typeof__(expr), type []))
    327 
    328 /* evaluates to true if expr is a string */
    329 #define _curl_is_string(expr)                                                 \
    330   (_curl_is_arr((expr), char) ||                                              \
    331    _curl_is_arr((expr), signed char) ||                                       \
    332    _curl_is_arr((expr), unsigned char))
    333 
    334 /* evaluates to true if expr is a long (no matter the signedness)
    335  * XXX: for now, int is also accepted (and therefore short and char, which
    336  * are promoted to int when passed to a variadic function) */
    337 #define _curl_is_long(expr)                                                   \
    338   (__builtin_types_compatible_p(__typeof__(expr), long) ||                    \
    339    __builtin_types_compatible_p(__typeof__(expr), signed long) ||             \
    340    __builtin_types_compatible_p(__typeof__(expr), unsigned long) ||           \
    341    __builtin_types_compatible_p(__typeof__(expr), int) ||                     \
    342    __builtin_types_compatible_p(__typeof__(expr), signed int) ||              \
    343    __builtin_types_compatible_p(__typeof__(expr), unsigned int) ||            \
    344    __builtin_types_compatible_p(__typeof__(expr), short) ||                   \
    345    __builtin_types_compatible_p(__typeof__(expr), signed short) ||            \
    346    __builtin_types_compatible_p(__typeof__(expr), unsigned short) ||          \
    347    __builtin_types_compatible_p(__typeof__(expr), char) ||                    \
    348    __builtin_types_compatible_p(__typeof__(expr), signed char) ||             \
    349    __builtin_types_compatible_p(__typeof__(expr), unsigned char))
    350 
    351 /* evaluates to true if expr is of type curl_off_t */
    352 #define _curl_is_off_t(expr)                                                  \
    353   (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
    354 
    355 /* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
    356 /* XXX: also check size of an char[] array? */
    357 #define _curl_is_error_buffer(expr)                                           \
    358   (__builtin_types_compatible_p(__typeof__(expr), char *) ||                  \
    359    __builtin_types_compatible_p(__typeof__(expr), char[]))
    360 
    361 /* evaluates to true if expr is of type (const) void* or (const) FILE* */
    362 #if 0
    363 #define _curl_is_cb_data(expr)                                                \
    364   (_curl_is_ptr((expr), void) ||                                              \
    365    _curl_is_ptr((expr), FILE))
    366 #else /* be less strict */
    367 #define _curl_is_cb_data(expr)                                                \
    368   _curl_is_any_ptr(expr)
    369 #endif
    370 
    371 /* evaluates to true if expr is of type FILE* */
    372 #define _curl_is_FILE(expr)                                                   \
    373   (__builtin_types_compatible_p(__typeof__(expr), FILE *))
    374 
    375 /* evaluates to true if expr can be passed as POST data (void* or char*) */
    376 #define _curl_is_postfields(expr)                                             \
    377   (_curl_is_ptr((expr), void) ||                                              \
    378    _curl_is_arr((expr), char))
    379 
    380 /* FIXME: the whole callback checking is messy...
    381  * The idea is to tolerate char vs. void and const vs. not const
    382  * pointers in arguments at least
    383  */
    384 /* helper: __builtin_types_compatible_p distinguishes between functions and
    385  * function pointers, hide it */
    386 #define _curl_callback_compatible(func, type)                                 \
    387   (__builtin_types_compatible_p(__typeof__(func), type) ||                    \
    388    __builtin_types_compatible_p(__typeof__(func), type*))
    389 
    390 /* evaluates to true if expr is of type curl_read_callback or "similar" */
    391 #define _curl_is_read_cb(expr)                                          \
    392   (_curl_is_NULL(expr) ||                                                     \
    393    __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) ||       \
    394    __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) ||      \
    395    _curl_callback_compatible((expr), _curl_read_callback1) ||                 \
    396    _curl_callback_compatible((expr), _curl_read_callback2) ||                 \
    397    _curl_callback_compatible((expr), _curl_read_callback3) ||                 \
    398    _curl_callback_compatible((expr), _curl_read_callback4) ||                 \
    399    _curl_callback_compatible((expr), _curl_read_callback5) ||                 \
    400    _curl_callback_compatible((expr), _curl_read_callback6))
    401 typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
    402 typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
    403 typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
    404 typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
    405 typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
    406 typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
    407 
    408 /* evaluates to true if expr is of type curl_write_callback or "similar" */
    409 #define _curl_is_write_cb(expr)                                               \
    410   (_curl_is_read_cb(expr) ||                                            \
    411    __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) ||      \
    412    __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) ||     \
    413    _curl_callback_compatible((expr), _curl_write_callback1) ||                \
    414    _curl_callback_compatible((expr), _curl_write_callback2) ||                \
    415    _curl_callback_compatible((expr), _curl_write_callback3) ||                \
    416    _curl_callback_compatible((expr), _curl_write_callback4) ||                \
    417    _curl_callback_compatible((expr), _curl_write_callback5) ||                \
    418    _curl_callback_compatible((expr), _curl_write_callback6))
    419 typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
    420 typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
    421                                        const void*);
    422 typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
    423 typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
    424 typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
    425                                        const void*);
    426 typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
    427 
    428 /* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
    429 #define _curl_is_ioctl_cb(expr)                                         \
    430   (_curl_is_NULL(expr) ||                                                     \
    431    __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) ||     \
    432    _curl_callback_compatible((expr), _curl_ioctl_callback1) ||                \
    433    _curl_callback_compatible((expr), _curl_ioctl_callback2) ||                \
    434    _curl_callback_compatible((expr), _curl_ioctl_callback3) ||                \
    435    _curl_callback_compatible((expr), _curl_ioctl_callback4))
    436 typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
    437 typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
    438 typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
    439 typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
    440 
    441 /* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
    442 #define _curl_is_sockopt_cb(expr)                                       \
    443   (_curl_is_NULL(expr) ||                                                     \
    444    __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) ||   \
    445    _curl_callback_compatible((expr), _curl_sockopt_callback1) ||              \
    446    _curl_callback_compatible((expr), _curl_sockopt_callback2))
    447 typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
    448 typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
    449                                       curlsocktype);
    450 
    451 /* evaluates to true if expr is of type curl_opensocket_callback or "similar" */
    452 #define _curl_is_opensocket_cb(expr)                                    \
    453   (_curl_is_NULL(expr) ||                                                     \
    454    __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
    455    _curl_callback_compatible((expr), _curl_opensocket_callback1) ||           \
    456    _curl_callback_compatible((expr), _curl_opensocket_callback2) ||           \
    457    _curl_callback_compatible((expr), _curl_opensocket_callback3) ||           \
    458    _curl_callback_compatible((expr), _curl_opensocket_callback4))
    459 typedef curl_socket_t (_curl_opensocket_callback1)
    460   (void *, curlsocktype, struct curl_sockaddr *);
    461 typedef curl_socket_t (_curl_opensocket_callback2)
    462   (void *, curlsocktype, const struct curl_sockaddr *);
    463 typedef curl_socket_t (_curl_opensocket_callback3)
    464   (const void *, curlsocktype, struct curl_sockaddr *);
    465 typedef curl_socket_t (_curl_opensocket_callback4)
    466   (const void *, curlsocktype, const struct curl_sockaddr *);
    467 
    468 /* evaluates to true if expr is of type curl_progress_callback or "similar" */
    469 #define _curl_is_progress_cb(expr)                                      \
    470   (_curl_is_NULL(expr) ||                                                     \
    471    __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) ||  \
    472    _curl_callback_compatible((expr), _curl_progress_callback1) ||             \
    473    _curl_callback_compatible((expr), _curl_progress_callback2))
    474 typedef int (_curl_progress_callback1)(void *,
    475     double, double, double, double);
    476 typedef int (_curl_progress_callback2)(const void *,
    477     double, double, double, double);
    478 
    479 /* evaluates to true if expr is of type curl_debug_callback or "similar" */
    480 #define _curl_is_debug_cb(expr)                                         \
    481   (_curl_is_NULL(expr) ||                                                     \
    482    __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) ||     \
    483    _curl_callback_compatible((expr), _curl_debug_callback1) ||                \
    484    _curl_callback_compatible((expr), _curl_debug_callback2) ||                \
    485    _curl_callback_compatible((expr), _curl_debug_callback3) ||                \
    486    _curl_callback_compatible((expr), _curl_debug_callback4))
    487 typedef int (_curl_debug_callback1) (CURL *,
    488     curl_infotype, char *, size_t, void *);
    489 typedef int (_curl_debug_callback2) (CURL *,
    490     curl_infotype, char *, size_t, const void *);
    491 typedef int (_curl_debug_callback3) (CURL *,
    492     curl_infotype, const char *, size_t, void *);
    493 typedef int (_curl_debug_callback4) (CURL *,
    494     curl_infotype, const char *, size_t, const void *);
    495 
    496 /* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
    497 /* this is getting even messier... */
    498 #define _curl_is_ssl_ctx_cb(expr)                                       \
    499   (_curl_is_NULL(expr) ||                                                     \
    500    __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) ||   \
    501    _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) ||              \
    502    _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) ||              \
    503    _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) ||              \
    504    _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) ||              \
    505    _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) ||              \
    506    _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) ||              \
    507    _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) ||              \
    508    _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
    509 typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
    510 typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
    511 typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
    512 typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
    513 #ifdef HEADER_SSL_H
    514 /* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
    515  * this will of course break if we're included before OpenSSL headers...
    516  */
    517 typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
    518 typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
    519 typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
    520 typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, const void *);
    521 #else
    522 typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
    523 typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
    524 typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
    525 typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
    526 #endif
    527 
    528 /* evaluates to true if expr is of type curl_conv_callback or "similar" */
    529 #define _curl_is_conv_cb(expr)                                          \
    530   (_curl_is_NULL(expr) ||                                                     \
    531    __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) ||      \
    532    _curl_callback_compatible((expr), _curl_conv_callback1) ||                 \
    533    _curl_callback_compatible((expr), _curl_conv_callback2) ||                 \
    534    _curl_callback_compatible((expr), _curl_conv_callback3) ||                 \
    535    _curl_callback_compatible((expr), _curl_conv_callback4))
    536 typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
    537 typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
    538 typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
    539 typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
    540 
    541 /* evaluates to true if expr is of type curl_seek_callback or "similar" */
    542 #define _curl_is_seek_cb(expr)                                          \
    543   (_curl_is_NULL(expr) ||                                                     \
    544    __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) ||      \
    545    _curl_callback_compatible((expr), _curl_seek_callback1) ||                 \
    546    _curl_callback_compatible((expr), _curl_seek_callback2))
    547 typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
    548 typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
    549 
    550 
    551 #endif /* __CURL_TYPECHECK_GCC_H */
    552