- Added curl_easy_getinfo typechecker.

- Added macros for curl_share_setopt and curl_multi_setopt to check at least
  the correct number of arguments.
This commit is contained in:
Michal Marek 2008-03-18 08:14:37 +00:00
Родитель 1380c9af9f
Коммит 6f3166c15b
7 изменённых файлов: 85 добавлений и 15 удалений

Просмотреть файл

@ -6,6 +6,12 @@
Changelog Changelog
Michal Marek (18 Mar 2008)
- Added curl_easy_getinfo typechecker.
- Added macros for curl_share_setopt and curl_multi_setopt to check at least
the correct number of arguments.
Daniel Fandrich (13 Mar 2008) Daniel Fandrich (13 Mar 2008)
- Added tests 622-625 to test SFTP/SCP uploads. Test 625 was an attempt to - Added tests 622-625 to test SFTP/SCP uploads. Test 625 was an attempt to
reproduce the --ftp-create-dirs problem reported by Brian Ulm, but that reproduce the --ftp-create-dirs problem reported by Brian Ulm, but that

Просмотреть файл

@ -17,10 +17,11 @@ This release includes the following changes:
o the test509-style setting URL in callback is officially no longer supported o the test509-style setting URL in callback is officially no longer supported
o support a full chain of certificates in a given PKCS12 certificate o support a full chain of certificates in a given PKCS12 certificate
o resumed transfers work with SFTP o resumed transfers work with SFTP
o added a type checking macro for curl_easy_setopt(), watch out for new o added type checking macros for curl_easy_setopt() and curl_easy_getinfo(),
warnings in code using libcurl (needs gcc-4.3 and currently only works watch out for new warnings in code using libcurl (needs gcc-4.3 and
in C mode) currently only works in C mode)
o curl_easy_setopt() uses are now checked to use three arguments o curl_easy_setopt(), curl_easy_getinfo(), curl_share_setopt() and
curl_multi_setopt() uses are now checked to use exactly three arguments
This release includes the following bugfixes: This release includes the following bugfixes:

Просмотреть файл

@ -1798,9 +1798,12 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#else #else
#if defined(__STDC__) && (__STDC__ >= 1) #if defined(__STDC__) && (__STDC__ >= 1)
/* This preprocessor magic that replaces a call with the exact same call is /* This preprocessor magic that replaces a call with the exact same call is
only done to make sure application authors use exactly three arguments only done to make sure application authors pass exactly three arguments
to this function. */ to these functions. */
#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) #define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
#endif /* __STDC__ >= 1 */ #endif /* __STDC__ >= 1 */
#endif /* gcc >= 4.3 && !__cplusplus */ #endif /* gcc >= 4.3 && !__cplusplus */

Просмотреть файл

@ -76,10 +76,10 @@ __extension__ ({ \
if (_curl_is_postfields_option(_curl_opt) && !_curl_is_postfields(value)) \ if (_curl_is_postfields_option(_curl_opt) && !_curl_is_postfields(value)) \
_curl_easy_setopt_err_postfields(); \ _curl_easy_setopt_err_postfields(); \
if ((_curl_opt) == CURLOPT_HTTPPOST && \ if ((_curl_opt) == CURLOPT_HTTPPOST && \
!_curl_is_ptr((value), struct curl_httppost)) \ !_curl_is_arr((value), struct curl_httppost)) \
_curl_easy_setopt_err_curl_httpost(); \ _curl_easy_setopt_err_curl_httpost(); \
if (_curl_is_slist_option(_curl_opt) && \ if (_curl_is_slist_option(_curl_opt) && \
!_curl_is_ptr((value), struct curl_slist)) \ !_curl_is_arr((value), struct curl_slist)) \
_curl_easy_setopt_err_curl_slist(); \ _curl_easy_setopt_err_curl_slist(); \
if ((_curl_opt) == CURLOPT_SHARE && !_curl_is_ptr((value), CURLSH)) \ if ((_curl_opt) == CURLOPT_SHARE && !_curl_is_ptr((value), CURLSH)) \
_curl_easy_setopt_err_CURLSH(); \ _curl_easy_setopt_err_CURLSH(); \
@ -87,10 +87,37 @@ __extension__ ({ \
curl_easy_setopt(handle, _curl_opt, value); \ curl_easy_setopt(handle, _curl_opt, value); \
}) })
/* wraps curl_easy_getinfo() with typechecking */
/* FIXME: don't allow const pointers */
#define curl_easy_getinfo(handle, info, arg) \
__extension__ ({ \
__typeof__ (info) _curl_info = info; \
if (__builtin_constant_p(_curl_info)) { \
if (_curl_is_string_info(_curl_info) && !_curl_is_arr((arg), char *)) \
_curl_easy_getinfo_err_string(); \
if (_curl_is_long_info(_curl_info) && !_curl_is_arr((arg), long)) \
_curl_easy_getinfo_err_long(); \
if (_curl_is_double_info(_curl_info) && !_curl_is_arr((arg), double)) \
_curl_easy_getinfo_err_double(); \
if (_curl_is_slist_info(_curl_info) && \
!_curl_is_arr((arg), struct curl_slist *)) \
_curl_easy_getinfo_err_curl_slist(); \
} \
curl_easy_getinfo(handle, _curl_info, arg); \
})
/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
* for now just make sure that the functions are called with three
* arguments
*/
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
/* the actual warnings, triggered by calling the _curl_easy_setopt_err* /* the actual warnings, triggered by calling the _curl_easy_setopt_err*
* functions */ * functions */
/* To define a new warning, use _CURL_WARNING(identifier, "message"); */ /* To define a new warning, use _CURL_WARNING(identifier, "message") */
#define _CURL_WARNING(id, message) \ #define _CURL_WARNING(id, message) \
static void __attribute__((warning(message))) __attribute__((unused)) \ static void __attribute__((warning(message))) __attribute__((unused)) \
__attribute__((noinline)) id(void) { __asm__(""); } __attribute__((noinline)) id(void) { __asm__(""); }
@ -136,7 +163,16 @@ _CURL_WARNING(_curl_easy_setopt_err_curl_slist,
_CURL_WARNING(_curl_easy_setopt_err_CURLSH, _CURL_WARNING(_curl_easy_setopt_err_CURLSH,
"curl_easy_setopt expects a CURLSH* argument for this option") "curl_easy_setopt expects a CURLSH* argument for this option")
/* groups of options that take the same type of argument */ _CURL_WARNING(_curl_easy_getinfo_err_string,
"curl_easy_getinfo expects a pointer to char * for this info")
_CURL_WARNING(_curl_easy_getinfo_err_long,
"curl_easy_getinfo expects a pointer to long for this info")
_CURL_WARNING(_curl_easy_getinfo_err_double,
"curl_easy_getinfo expects a pointer to double for this info")
_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
"curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
/* groups of curl_easy_setops options that take the same type of argument */
/* To add a new option to one of the groups, just add /* To add a new option to one of the groups, just add
* (option) == CURLOPT_SOMETHING * (option) == CURLOPT_SOMETHING
@ -230,13 +266,34 @@ _CURL_WARNING(_curl_easy_setopt_err_CURLSH,
(option) == CURLOPT_TELNETOPTIONS || \ (option) == CURLOPT_TELNETOPTIONS || \
0) 0)
/* groups of curl_easy_getinfo infos that take the same type of argument */
/* evaluates to true if info expects a pointer to char * argument */
#define _curl_is_string_info(info) \
(CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
/* evaluates to true if info expects a pointer to long argument */
#define _curl_is_long_info(info) \
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
/* evaluates to true if info expects a pointer to double argument */
#define _curl_is_double_info(info) \
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
/* evaluates to true if info expects a pointer to struct curl_slist * argument */
#define _curl_is_slist_info(info) \
(CURLINFO_SLIST < (info))
/* typecheck helpers -- check whether given expression has requested type*/ /* typecheck helpers -- check whether given expression has requested type*/
/* For pointers, you can use the _curl_is_ptr macro, otherwise define a new /* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
* macro. Search for __builtin_types_compatible_p in the GCC manual. NOTE: * otherwise define a new macro. Search for __builtin_types_compatible_p
* these macros MUST NOT EVALUATE their arguments! The argument is the actual * in the GCC manual.
* expression passed to the curl_easy_setopt macro. This means that you can * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
* only apply the sizeof and __typeof__ operators, no == or whatsoever. * the actual expression passed to the curl_easy_setopt macro. This
* means that you can only apply the sizeof and __typeof__ operators, no
* == or whatsoever.
*/ */
/* XXX: should evaluate to true iff expr is a pointer */ /* XXX: should evaluate to true iff expr is a pointer */

Просмотреть файл

@ -548,6 +548,7 @@ void Curl_easy_initHandleData(struct SessionHandle *data)
* curl_easy_getinfo() is an external interface that allows an app to retrieve * curl_easy_getinfo() is an external interface that allows an app to retrieve
* information from a performed transfer and similar. * information from a performed transfer and similar.
*/ */
#undef curl_easy_getinfo
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...) CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
{ {
va_list arg; va_list arg;

Просмотреть файл

@ -1778,6 +1778,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
return result; return result;
} }
#undef curl_multi_setopt
CURLMcode curl_multi_setopt(CURLM *multi_handle, CURLMcode curl_multi_setopt(CURLM *multi_handle,
CURLMoption option, ...) CURLMoption option, ...)
{ {

Просмотреть файл

@ -46,6 +46,7 @@ curl_share_init(void)
return share; return share;
} }
#undef curl_share_setopt
CURLSHcode CURLSHcode
curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
{ {