当前位置: 技术问答>linux和unix
glibc源码问题
来源: 互联网 发布时间:2017-05-29
本文导语: 本帖最后由 caoshufengcao 于 2014-09-19 10:23:08 编辑 有一段代码不知道用了什么语法: wcrtomb函数的源码如下: 我对DL_CALL_FCT这个宏不大了解,这是用了什么语法? static mbstate_t state; size_t __wcrtomb (char *s, wchar_t wc, mbsta...
wcrtomb函数的源码如下:
我对DL_CALL_FCT这个宏不大了解,这是用了什么语法?
static mbstate_t state;
size_t
__wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
{
char buf[MB_CUR_MAX];
struct __gconv_step_data data;
int status;
size_t result;
size_t dummy;
const struct gconv_fcts *fcts;
/* Set information for this step. */
data.__invocation_counter = 0;
data.__internal_use = 1;
data.__flags = __GCONV_IS_LAST;
data.__statep = ps ?: &state;
data.__trans = NULL;
/* A first special case is if S is NULL. This means put PS in the
initial state. */
if (s == NULL)
s = buf;
wc = L'';
}
/* Tell where we want to have the result. */
data.__outbuf = (unsigned char *) s;
data.__outbufend = (unsigned char *) s + MB_CUR_MAX;
/* Get the conversion functions. */
fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
__gconv_fct fct = fcts->tomb->__fct;
#ifdef PTR_DEMANGLE
if (fcts->tomb->__shlib_handle != NULL)
PTR_DEMANGLE (fct);
#endif
/* If WC is the NUL character we write into the output buffer the byte
sequence necessary for PS to get into the initial state, followed
by a NUL byte. */
if (wc == L'')
{
status = DL_CALL_FCT (fct, (fcts->tomb, &data, NULL, NULL,
NULL, &dummy, 1, 1));
if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
*data.__outbuf++ = '';
}
else
{
/* Do a normal conversion. */
const unsigned char *inbuf = (const unsigned char *) &wc;
status = DL_CALL_FCT (fct,
(fcts->tomb, &data, &inbuf,
inbuf + sizeof (wchar_t), NULL, &dummy, 0, 1));
}
/* There must not be any problems with the conversion but illegal input
characters. The output buffer must be large enough, otherwise the
definition of MB_CUR_MAX is not correct. All the other possible
errors also must not happen. */
assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
|| status == __GCONV_ILLEGAL_INPUT
|| status == __GCONV_INCOMPLETE_INPUT
|| status == __GCONV_FULL_OUTPUT);
if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
|| status == __GCONV_FULL_OUTPUT)
result = data.__outbuf - (unsigned char *) s;
else
{
result = (size_t) -1;
__set_errno (EILSEQ);
}
return result;
}
DL_CALL_FCT宏最后转化为如下:
status = (_dl_mcount_wrapper_check ((void *) (fct)), (*(fct)) (fcts->tomb, &data, &inbuf, inbuf + sizeof (wchar_t), ((void *)0), &dummy, 0, 1))
以下是DL_CALL_FCT的定义:
/* To support profiling of shared objects it is a good idea to call
the function found using `dlsym' using the following macro since
these calls do not use the PLT. But this would mean the dynamic
loader has no chance to find out when the function is called. The
macro applies the necessary magic so that profiling is possible.
Rewrite
foo = (*fctp) (arg1, arg2);
into
foo = DL_CALL_FCT (fctp, (arg1, arg2));
*/
# define DL_CALL_FCT(fctp, args)
(_dl_mcount_wrapper_check ((void *) (fctp)), (*(fctp)) args)
另外_dl_mcount_wrapper_check这个函数的返回类型是void它怎么能给status赋值呢?
这是用的gcc的什么特性吗?
|
就是简单的宏展开。
赋值给status的不是_dl_mcount_wrapper_check函数。你注意看一下括号。
status后面是个逗号分隔表达式,首先用_dl_mcount_wrapper_check检查 fct,然后调用fct将返回值赋给status。
赋值给status的不是_dl_mcount_wrapper_check函数。你注意看一下括号。
status后面是个逗号分隔表达式,首先用_dl_mcount_wrapper_check检查 fct,然后调用fct将返回值赋给status。