- Igor Novoseltsev brought a patch that introduced two new options to
[platform/upstream/curl.git] / include / curl / typecheck-gcc.h
1 #ifndef __CURL_TYPECHECK_GCC_H
2 #define __CURL_TYPECHECK_GCC_H
3 /***************************************************************************
4  *                                  _   _ ____  _
5  *  Project                     ___| | | |  _ \| |
6  *                             / __| | | | |_) | |
7  *                            | (__| |_| |  _ <| |___
8  *                             \___|\___/|_| \_\_____|
9  *
10  * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@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$
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_ENCODING ||                                            \
203    (option) == CURLOPT_REFERER ||                                             \
204    (option) == CURLOPT_USERAGENT ||                                           \
205    (option) == CURLOPT_COOKIE ||                                              \
206    (option) == CURLOPT_COOKIEFILE ||                                          \
207    (option) == CURLOPT_COOKIEJAR ||                                           \
208    (option) == CURLOPT_COOKIELIST ||                                          \
209    (option) == CURLOPT_FTPPORT ||                                             \
210    (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER ||                             \
211    (option) == CURLOPT_FTP_ACCOUNT ||                                         \
212    (option) == CURLOPT_RANGE ||                                               \
213    (option) == CURLOPT_CUSTOMREQUEST ||                                       \
214    (option) == CURLOPT_SSLCERT ||                                             \
215    (option) == CURLOPT_SSLCERTTYPE ||                                         \
216    (option) == CURLOPT_SSLKEY ||                                              \
217    (option) == CURLOPT_SSLKEYTYPE ||                                          \
218    (option) == CURLOPT_KEYPASSWD ||                                           \
219    (option) == CURLOPT_SSLENGINE ||                                           \
220    (option) == CURLOPT_CAINFO ||                                              \
221    (option) == CURLOPT_CAPATH ||                                              \
222    (option) == CURLOPT_RANDOM_FILE ||                                         \
223    (option) == CURLOPT_EGDSOCKET ||                                           \
224    (option) == CURLOPT_SSL_CIPHER_LIST ||                                     \
225    (option) == CURLOPT_KRBLEVEL ||                                            \
226    (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 ||                             \
227    (option) == CURLOPT_SSH_PUBLIC_KEYFILE ||                                  \
228    (option) == CURLOPT_SSH_PRIVATE_KEYFILE ||                                 \
229    (option) == CURLOPT_CRLFILE ||                                             \
230    (option) == CURLOPT_ISSUERCERT ||                                          \
231    0)
232
233 /* evaluates to true if option takes a curl_write_callback argument */
234 #define _curl_is_write_cb_option(option)                                      \
235   ((option) == CURLOPT_HEADERFUNCTION ||                                      \
236    (option) == CURLOPT_WRITEFUNCTION)
237
238 /* evaluates to true if option takes a curl_conv_callback argument */
239 #define _curl_is_conv_cb_option(option)                                       \
240   ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION ||                            \
241    (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION ||                          \
242    (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
243
244 /* evaluates to true if option takes a data argument to pass to a callback */
245 #define _curl_is_cb_data_option(option)                                       \
246   ((option) == CURLOPT_WRITEDATA ||                                           \
247    (option) == CURLOPT_READDATA ||                                            \
248    (option) == CURLOPT_IOCTLDATA ||                                           \
249    (option) == CURLOPT_SOCKOPTDATA ||                                         \
250    (option) == CURLOPT_OPENSOCKETDATA ||                                      \
251    (option) == CURLOPT_PROGRESSDATA ||                                        \
252    (option) == CURLOPT_WRITEHEADER ||                                         \
253    (option) == CURLOPT_DEBUGDATA ||                                           \
254    (option) == CURLOPT_SSL_CTX_DATA ||                                        \
255    (option) == CURLOPT_SEEKDATA ||                                            \
256    (option) == CURLOPT_PRIVATE ||                                             \
257    0)
258
259 /* evaluates to true if option takes a POST data argument (void* or char*) */
260 #define _curl_is_postfields_option(option)                                    \
261   ((option) == CURLOPT_POSTFIELDS ||                                          \
262    (option) == CURLOPT_COPYPOSTFIELDS ||                                      \
263    0)
264
265 /* evaluates to true if option takes a struct curl_slist * argument */
266 #define _curl_is_slist_option(option)                                         \
267   ((option) == CURLOPT_HTTPHEADER ||                                          \
268    (option) == CURLOPT_HTTP200ALIASES ||                                      \
269    (option) == CURLOPT_QUOTE ||                                               \
270    (option) == CURLOPT_POSTQUOTE ||                                           \
271    (option) == CURLOPT_PREQUOTE ||                                            \
272    (option) == CURLOPT_TELNETOPTIONS ||                                       \
273    0)
274
275 /* groups of curl_easy_getinfo infos that take the same type of argument */
276
277 /* evaluates to true if info expects a pointer to char * argument */
278 #define _curl_is_string_info(info)                                            \
279   (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
280
281 /* evaluates to true if info expects a pointer to long argument */
282 #define _curl_is_long_info(info)                                              \
283   (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
284
285 /* evaluates to true if info expects a pointer to double argument */
286 #define _curl_is_double_info(info)                                            \
287   (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
288
289 /* true if info expects a pointer to struct curl_slist * argument */
290 #define _curl_is_slist_info(info)                                             \
291   (CURLINFO_SLIST < (info))
292
293
294 /* typecheck helpers -- check whether given expression has requested type*/
295
296 /* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
297  * otherwise define a new macro. Search for __builtin_types_compatible_p
298  * in the GCC manual.
299  * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
300  * the actual expression passed to the curl_easy_setopt macro. This
301  * means that you can only apply the sizeof and __typeof__ operators, no
302  * == or whatsoever.
303  */
304
305 /* XXX: should evaluate to true iff expr is a pointer */
306 #define _curl_is_any_ptr(expr)                                                \
307   (sizeof(expr) == sizeof(void*))
308
309 /* evaluates to true if expr is NULL */
310 /* XXX: must not evaluate expr, so this check is not accurate */
311 #define _curl_is_NULL(expr)                                                   \
312   (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
313
314 /* evaluates to true if expr is type*, const type* or NULL */
315 #define _curl_is_ptr(expr, type)                                              \
316   (_curl_is_NULL(expr) ||                                                     \
317    __builtin_types_compatible_p(__typeof__(expr), type *) ||                  \
318    __builtin_types_compatible_p(__typeof__(expr), const type *))
319
320 /* evaluates to true if expr is one of type[], type*, NULL or const type* */
321 #define _curl_is_arr(expr, type)                                              \
322   (_curl_is_ptr((expr), type) ||                                              \
323    __builtin_types_compatible_p(__typeof__(expr), type []))
324
325 /* evaluates to true if expr is a string */
326 #define _curl_is_string(expr)                                                 \
327   (_curl_is_arr((expr), char) ||                                              \
328    _curl_is_arr((expr), signed char) ||                                       \
329    _curl_is_arr((expr), unsigned char))
330
331 /* evaluates to true if expr is a long (no matter the signedness)
332  * XXX: for now, int is also accepted (and therefore short and char, which
333  * are promoted to int when passed to a variadic function) */
334 #define _curl_is_long(expr)                                                   \
335   (__builtin_types_compatible_p(__typeof__(expr), long) ||                    \
336    __builtin_types_compatible_p(__typeof__(expr), signed long) ||             \
337    __builtin_types_compatible_p(__typeof__(expr), unsigned long) ||           \
338    __builtin_types_compatible_p(__typeof__(expr), int) ||                     \
339    __builtin_types_compatible_p(__typeof__(expr), signed int) ||              \
340    __builtin_types_compatible_p(__typeof__(expr), unsigned int) ||            \
341    __builtin_types_compatible_p(__typeof__(expr), short) ||                   \
342    __builtin_types_compatible_p(__typeof__(expr), signed short) ||            \
343    __builtin_types_compatible_p(__typeof__(expr), unsigned short) ||          \
344    __builtin_types_compatible_p(__typeof__(expr), char) ||                    \
345    __builtin_types_compatible_p(__typeof__(expr), signed char) ||             \
346    __builtin_types_compatible_p(__typeof__(expr), unsigned char))
347
348 /* evaluates to true if expr is of type curl_off_t */
349 #define _curl_is_off_t(expr)                                                  \
350   (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
351
352 /* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
353 /* XXX: also check size of an char[] array? */
354 #define _curl_is_error_buffer(expr)                                           \
355   (__builtin_types_compatible_p(__typeof__(expr), char *) ||                  \
356    __builtin_types_compatible_p(__typeof__(expr), char[]))
357
358 /* evaluates to true if expr is of type (const) void* or (const) FILE* */
359 #if 0
360 #define _curl_is_cb_data(expr)                                                \
361   (_curl_is_ptr((expr), void) ||                                              \
362    _curl_is_ptr((expr), FILE))
363 #else /* be less strict */
364 #define _curl_is_cb_data(expr)                                                \
365   _curl_is_any_ptr(expr)
366 #endif
367
368 /* evaluates to true if expr is of type FILE* */
369 #define _curl_is_FILE(expr)                                                   \
370   (__builtin_types_compatible_p(__typeof__(expr), FILE *))
371
372 /* evaluates to true if expr can be passed as POST data (void* or char*) */
373 #define _curl_is_postfields(expr)                                             \
374   (_curl_is_ptr((expr), void) ||                                              \
375    _curl_is_arr((expr), char))
376
377 /* FIXME: the whole callback checking is messy...
378  * The idea is to tolerate char vs. void and const vs. not const
379  * pointers in arguments at least
380  */
381 /* helper: __builtin_types_compatible_p distinguishes between functions and
382  * function pointers, hide it */
383 #define _curl_callback_compatible(func, type)                                 \
384   (__builtin_types_compatible_p(__typeof__(func), type) ||                    \
385    __builtin_types_compatible_p(__typeof__(func), type*))
386
387 /* evaluates to true if expr is of type curl_read_callback or "similar" */
388 #define _curl_is_read_cb(expr)                                          \
389   (_curl_is_NULL(expr) ||                                                     \
390    __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) ||       \
391    __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) ||      \
392    _curl_callback_compatible((expr), _curl_read_callback1) ||                 \
393    _curl_callback_compatible((expr), _curl_read_callback2) ||                 \
394    _curl_callback_compatible((expr), _curl_read_callback3) ||                 \
395    _curl_callback_compatible((expr), _curl_read_callback4) ||                 \
396    _curl_callback_compatible((expr), _curl_read_callback5) ||                 \
397    _curl_callback_compatible((expr), _curl_read_callback6))
398 typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
399 typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
400 typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
401 typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
402 typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
403 typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
404
405 /* evaluates to true if expr is of type curl_write_callback or "similar" */
406 #define _curl_is_write_cb(expr)                                               \
407   (_curl_is_read_cb(expr) ||                                            \
408    __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) ||      \
409    __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) ||     \
410    _curl_callback_compatible((expr), _curl_write_callback1) ||                \
411    _curl_callback_compatible((expr), _curl_write_callback2) ||                \
412    _curl_callback_compatible((expr), _curl_write_callback3) ||                \
413    _curl_callback_compatible((expr), _curl_write_callback4) ||                \
414    _curl_callback_compatible((expr), _curl_write_callback5) ||                \
415    _curl_callback_compatible((expr), _curl_write_callback6))
416 typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
417 typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
418                                        const void*);
419 typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
420 typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
421 typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
422                                        const void*);
423 typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
424
425 /* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
426 #define _curl_is_ioctl_cb(expr)                                         \
427   (_curl_is_NULL(expr) ||                                                     \
428    __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) ||     \
429    _curl_callback_compatible((expr), _curl_ioctl_callback1) ||                \
430    _curl_callback_compatible((expr), _curl_ioctl_callback2) ||                \
431    _curl_callback_compatible((expr), _curl_ioctl_callback3) ||                \
432    _curl_callback_compatible((expr), _curl_ioctl_callback4))
433 typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
434 typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
435 typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
436 typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
437
438 /* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
439 #define _curl_is_sockopt_cb(expr)                                       \
440   (_curl_is_NULL(expr) ||                                                     \
441    __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) ||   \
442    _curl_callback_compatible((expr), _curl_sockopt_callback1) ||              \
443    _curl_callback_compatible((expr), _curl_sockopt_callback2))
444 typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
445 typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
446                                       curlsocktype);
447
448 /* evaluates to true if expr is of type curl_opensocket_callback or "similar" */
449 #define _curl_is_opensocket_cb(expr)                                    \
450   (_curl_is_NULL(expr) ||                                                     \
451    __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
452    _curl_callback_compatible((expr), _curl_opensocket_callback1) ||           \
453    _curl_callback_compatible((expr), _curl_opensocket_callback2) ||           \
454    _curl_callback_compatible((expr), _curl_opensocket_callback3) ||           \
455    _curl_callback_compatible((expr), _curl_opensocket_callback4))
456 typedef curl_socket_t (_curl_opensocket_callback1)
457   (void *, curlsocktype, struct curl_sockaddr *);
458 typedef curl_socket_t (_curl_opensocket_callback2)
459   (void *, curlsocktype, const struct curl_sockaddr *);
460 typedef curl_socket_t (_curl_opensocket_callback3)
461   (const void *, curlsocktype, struct curl_sockaddr *);
462 typedef curl_socket_t (_curl_opensocket_callback4)
463   (const void *, curlsocktype, const struct curl_sockaddr *);
464
465 /* evaluates to true if expr is of type curl_progress_callback or "similar" */
466 #define _curl_is_progress_cb(expr)                                      \
467   (_curl_is_NULL(expr) ||                                                     \
468    __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) ||  \
469    _curl_callback_compatible((expr), _curl_progress_callback1) ||             \
470    _curl_callback_compatible((expr), _curl_progress_callback2))
471 typedef int (_curl_progress_callback1)(void *,
472     double, double, double, double);
473 typedef int (_curl_progress_callback2)(const void *,
474     double, double, double, double);
475
476 /* evaluates to true if expr is of type curl_debug_callback or "similar" */
477 #define _curl_is_debug_cb(expr)                                         \
478   (_curl_is_NULL(expr) ||                                                     \
479    __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) ||     \
480    _curl_callback_compatible((expr), _curl_debug_callback1) ||                \
481    _curl_callback_compatible((expr), _curl_debug_callback2) ||                \
482    _curl_callback_compatible((expr), _curl_debug_callback3) ||                \
483    _curl_callback_compatible((expr), _curl_debug_callback4))
484 typedef int (_curl_debug_callback1) (CURL *,
485     curl_infotype, char *, size_t, void *);
486 typedef int (_curl_debug_callback2) (CURL *,
487     curl_infotype, char *, size_t, const void *);
488 typedef int (_curl_debug_callback3) (CURL *,
489     curl_infotype, const char *, size_t, void *);
490 typedef int (_curl_debug_callback4) (CURL *,
491     curl_infotype, const char *, size_t, const void *);
492
493 /* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
494 /* this is getting even messier... */
495 #define _curl_is_ssl_ctx_cb(expr)                                       \
496   (_curl_is_NULL(expr) ||                                                     \
497    __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) ||   \
498    _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) ||              \
499    _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) ||              \
500    _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) ||              \
501    _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) ||              \
502    _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) ||              \
503    _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) ||              \
504    _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) ||              \
505    _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
506 typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
507 typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
508 typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
509 typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
510 #ifdef HEADER_SSL_H
511 /* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
512  * this will of course break if we're included before OpenSSL headers...
513  */
514 typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
515 typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
516 typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
517 typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, const void *);
518 #else
519 typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
520 typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
521 typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
522 typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
523 #endif
524
525 /* evaluates to true if expr is of type curl_conv_callback or "similar" */
526 #define _curl_is_conv_cb(expr)                                          \
527   (_curl_is_NULL(expr) ||                                                     \
528    __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) ||      \
529    _curl_callback_compatible((expr), _curl_conv_callback1) ||                 \
530    _curl_callback_compatible((expr), _curl_conv_callback2) ||                 \
531    _curl_callback_compatible((expr), _curl_conv_callback3) ||                 \
532    _curl_callback_compatible((expr), _curl_conv_callback4))
533 typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
534 typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
535 typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
536 typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
537
538 /* evaluates to true if expr is of type curl_seek_callback or "similar" */
539 #define _curl_is_seek_cb(expr)                                          \
540   (_curl_is_NULL(expr) ||                                                     \
541    __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) ||      \
542    _curl_callback_compatible((expr), _curl_seek_callback1) ||                 \
543    _curl_callback_compatible((expr), _curl_seek_callback2))
544 typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
545 typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
546
547
548 #endif /* __CURL_TYPECHECK_GCC_H */