- 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
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)
- 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

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

@ -17,10 +17,11 @@ This release includes the following changes:
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 resumed transfers work with SFTP
o added a type checking macro for curl_easy_setopt(), watch out for new
warnings in code using libcurl (needs gcc-4.3 and currently only works
in C mode)
o curl_easy_setopt() uses are now checked to use three arguments
o added type checking macros for curl_easy_setopt() and curl_easy_getinfo(),
watch out for new warnings in code using libcurl (needs gcc-4.3 and
currently only works in C mode)
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:

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

@ -1798,9 +1798,12 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#else
#if defined(__STDC__) && (__STDC__ >= 1)
/* This preprocessor magic that replaces a call with the exact same call is
only done to make sure application authors use exactly three arguments
to this function. */
only done to make sure application authors pass exactly three arguments
to these functions. */
#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 /* gcc >= 4.3 && !__cplusplus */

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

@ -76,10 +76,10 @@ __extension__ ({ \
if (_curl_is_postfields_option(_curl_opt) && !_curl_is_postfields(value)) \
_curl_easy_setopt_err_postfields(); \
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(); \
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(); \
if ((_curl_opt) == CURLOPT_SHARE && !_curl_is_ptr((value), CURLSH)) \
_curl_easy_setopt_err_CURLSH(); \
@ -87,10 +87,37 @@ __extension__ ({ \
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*
* 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) \
static void __attribute__((warning(message))) __attribute__((unused)) \
__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_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
* (option) == CURLOPT_SOMETHING
@ -230,13 +266,34 @@ _CURL_WARNING(_curl_easy_setopt_err_CURLSH,
(option) == CURLOPT_TELNETOPTIONS || \
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*/
/* For pointers, you can use the _curl_is_ptr macro, otherwise define a new
* macro. Search for __builtin_types_compatible_p in the GCC manual. NOTE:
* these macros MUST NOT EVALUATE their arguments! The argument is 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.
/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
* otherwise define a new macro. Search for __builtin_types_compatible_p
* in the GCC manual.
* NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
* 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 */

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

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

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

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

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

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