Defined a proper structure for debug channels.
Also put all the function pointers inside a structure and added __wine_dbg_set_functions to change them instead of exporting the pointers directly.
This commit is contained in:
parent
170278dfe0
commit
75c27e17b6
|
@ -282,7 +282,7 @@ static int NTDLL_dbg_vprintf( const char *format, va_list args )
|
|||
/***********************************************************************
|
||||
* NTDLL_dbg_vlog
|
||||
*/
|
||||
static int NTDLL_dbg_vlog( unsigned int cls, const char *channel,
|
||||
static int NTDLL_dbg_vlog( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
|
||||
const char *function, const char *format, va_list args )
|
||||
{
|
||||
static const char * const classes[] = { "fixme", "err", "warn", "trace" };
|
||||
|
@ -295,13 +295,23 @@ static int NTDLL_dbg_vlog( unsigned int cls, const char *channel,
|
|||
if (TRACE_ON(tid))
|
||||
ret = wine_dbg_printf( "%04lx:", GetCurrentThreadId() );
|
||||
if (cls < sizeof(classes)/sizeof(classes[0]))
|
||||
ret += wine_dbg_printf( "%s:%s:%s ", classes[cls], channel + 1, function );
|
||||
ret += wine_dbg_printf( "%s:%s:%s ", classes[cls], channel->name, function );
|
||||
}
|
||||
if (format)
|
||||
ret += NTDLL_dbg_vprintf( format, args );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static const struct __wine_debug_functions funcs =
|
||||
{
|
||||
NTDLL_dbgstr_an,
|
||||
NTDLL_dbgstr_wn,
|
||||
NTDLL_dbg_vsprintf,
|
||||
NTDLL_dbg_vprintf,
|
||||
NTDLL_dbg_vlog
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* debug_init
|
||||
*/
|
||||
|
@ -309,10 +319,6 @@ void debug_init(void)
|
|||
{
|
||||
extern void __wine_dbg_ntdll_init(void);
|
||||
|
||||
__wine_dbgstr_an = NTDLL_dbgstr_an;
|
||||
__wine_dbgstr_wn = NTDLL_dbgstr_wn;
|
||||
__wine_dbg_vsprintf = NTDLL_dbg_vsprintf;
|
||||
__wine_dbg_vprintf = NTDLL_dbg_vprintf;
|
||||
__wine_dbg_vlog = NTDLL_dbg_vlog;
|
||||
__wine_dbg_set_functions( &funcs, sizeof(funcs) );
|
||||
__wine_dbg_ntdll_init(); /* hack: register debug channels early */
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ struct _GUID;
|
|||
* Internal definitions (do not use these directly)
|
||||
*/
|
||||
|
||||
enum __WINE_DEBUG_CLASS {
|
||||
enum __wine_debug_class
|
||||
{
|
||||
__WINE_DBCL_FIXME,
|
||||
__WINE_DBCL_ERR,
|
||||
__WINE_DBCL_WARN,
|
||||
|
@ -45,22 +46,28 @@ enum __WINE_DEBUG_CLASS {
|
|||
__WINE_DBCL_COUNT
|
||||
};
|
||||
|
||||
struct __wine_debug_channel
|
||||
{
|
||||
unsigned char flags;
|
||||
char name[15];
|
||||
};
|
||||
|
||||
#ifndef WINE_NO_TRACE_MSGS
|
||||
# define __WINE_GET_DEBUGGING_TRACE(dbch) ((dbch)[0] & (1 << __WINE_DBCL_TRACE))
|
||||
# define __WINE_GET_DEBUGGING_TRACE(dbch) ((dbch)->flags & (1 << __WINE_DBCL_TRACE))
|
||||
#else
|
||||
# define __WINE_GET_DEBUGGING_TRACE(dbch) 0
|
||||
#endif
|
||||
|
||||
#ifndef WINE_NO_DEBUG_MSGS
|
||||
# define __WINE_GET_DEBUGGING_WARN(dbch) ((dbch)[0] & (1 << __WINE_DBCL_WARN))
|
||||
# define __WINE_GET_DEBUGGING_FIXME(dbch) ((dbch)[0] & (1 << __WINE_DBCL_FIXME))
|
||||
# define __WINE_GET_DEBUGGING_WARN(dbch) ((dbch)->flags & (1 << __WINE_DBCL_WARN))
|
||||
# define __WINE_GET_DEBUGGING_FIXME(dbch) ((dbch)->flags & (1 << __WINE_DBCL_FIXME))
|
||||
#else
|
||||
# define __WINE_GET_DEBUGGING_WARN(dbch) 0
|
||||
# define __WINE_GET_DEBUGGING_FIXME(dbch) 0
|
||||
#endif
|
||||
|
||||
/* define error macro regardless of what is configured */
|
||||
#define __WINE_GET_DEBUGGING_ERR(dbch) ((dbch)[0] & (1 << __WINE_DBCL_ERR))
|
||||
#define __WINE_GET_DEBUGGING_ERR(dbch) ((dbch)->flags & (1 << __WINE_DBCL_ERR))
|
||||
|
||||
#define __WINE_GET_DEBUGGING(dbcl,dbch) __WINE_GET_DEBUGGING##dbcl(dbch)
|
||||
#define __WINE_SET_DEBUGGING(dbcl,dbch,on) \
|
||||
|
@ -70,8 +77,8 @@ enum __WINE_DEBUG_CLASS {
|
|||
|
||||
#define __WINE_DPRINTF(dbcl,dbch) \
|
||||
do { if(__WINE_GET_DEBUGGING(dbcl,(dbch))) { \
|
||||
const char * const __dbch = (dbch); \
|
||||
const enum __WINE_DEBUG_CLASS __dbcl = __WINE_DBCL##dbcl; \
|
||||
struct __wine_debug_channel * const __dbch = (dbch); \
|
||||
const enum __wine_debug_class __dbcl = __WINE_DBCL##dbcl; \
|
||||
__WINE_DBG_LOG
|
||||
|
||||
#define __WINE_DBG_LOG(args...) \
|
||||
|
@ -96,7 +103,7 @@ enum __WINE_DEBUG_CLASS {
|
|||
|
||||
#define __WINE_DPRINTF(dbcl,dbch) \
|
||||
do { if(__WINE_GET_DEBUGGING(dbcl,(dbch))) { \
|
||||
const char * const __dbch = (dbch); \
|
||||
struct __wine_debug_channel * const __dbch = (dbch); \
|
||||
const enum __WINE_DEBUG_CLASS __dbcl = __WINE_DBCL##dbcl; \
|
||||
__WINE_DBG_LOG
|
||||
|
||||
|
@ -128,6 +135,17 @@ enum __WINE_DEBUG_CLASS {
|
|||
|
||||
#endif /* !__GNUC__ && !__SUNPRO_C */
|
||||
|
||||
struct __wine_debug_functions
|
||||
{
|
||||
const char * (*dbgstr_an)( const char * s, int n );
|
||||
const char * (*dbgstr_wn)( const WCHAR *s, int n );
|
||||
const char * (*dbg_vsprintf)( const char *format, va_list args );
|
||||
int (*dbg_vprintf)( const char *format, va_list args );
|
||||
int (*dbg_vlog)( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
|
||||
const char *function, const char *format, va_list args );
|
||||
};
|
||||
|
||||
extern void __wine_dbg_set_functions( const struct __wine_debug_functions *funcs, size_t size );
|
||||
|
||||
/*
|
||||
* Exported definitions and macros
|
||||
|
@ -138,14 +156,22 @@ enum __WINE_DEBUG_CLASS {
|
|||
as strings are re-used. */
|
||||
extern const char *wine_dbgstr_an( const char * s, int n );
|
||||
extern const char *wine_dbgstr_wn( const WCHAR *s, int n );
|
||||
extern const char *wine_dbgstr_a( const char *s );
|
||||
extern const char *wine_dbgstr_w( const WCHAR *s );
|
||||
extern const char *wine_dbg_sprintf( const char *format, ... ) __WINE_PRINTF_ATTR(1,2);
|
||||
|
||||
extern int wine_dbg_printf( const char *format, ... ) __WINE_PRINTF_ATTR(1,2);
|
||||
extern int wine_dbg_log( unsigned int cls, const char *ch, const char *func,
|
||||
extern int wine_dbg_log( enum __wine_debug_class cls, struct __wine_debug_channel *ch, const char *func,
|
||||
const char *format, ... ) __WINE_PRINTF_ATTR(4,5);
|
||||
|
||||
extern inline const char *wine_dbgstr_a( const char *s )
|
||||
{
|
||||
return wine_dbgstr_an( s, -1 );
|
||||
}
|
||||
|
||||
extern inline const char *wine_dbgstr_w( const WCHAR *s )
|
||||
{
|
||||
return wine_dbgstr_wn( s, -1 );
|
||||
}
|
||||
|
||||
static inline const char *wine_dbgstr_guid( const GUID *id )
|
||||
{
|
||||
if (!id) return "(null)";
|
||||
|
@ -176,37 +202,38 @@ static inline const char *wine_dbgstr_rect( const RECT *rect )
|
|||
|
||||
static inline const char *wine_dbgstr_longlong( ULONGLONG ll )
|
||||
{
|
||||
if (ll >> 32) return wine_dbg_sprintf( "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll );
|
||||
if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
|
||||
return wine_dbg_sprintf( "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll );
|
||||
else return wine_dbg_sprintf( "%lx", (unsigned long)ll );
|
||||
}
|
||||
|
||||
#ifndef WINE_TRACE
|
||||
#define WINE_TRACE __WINE_DPRINTF(_TRACE,__wine_dbch___default)
|
||||
#define WINE_TRACE_(ch) __WINE_DPRINTF(_TRACE,__wine_dbch_##ch)
|
||||
#define WINE_TRACE_(ch) __WINE_DPRINTF(_TRACE,&__wine_dbch_##ch)
|
||||
#endif
|
||||
#define WINE_TRACE_ON(ch) __WINE_GET_DEBUGGING(_TRACE,__wine_dbch_##ch)
|
||||
#define WINE_TRACE_ON(ch) __WINE_GET_DEBUGGING(_TRACE,&__wine_dbch_##ch)
|
||||
|
||||
#ifndef WINE_WARN
|
||||
#define WINE_WARN __WINE_DPRINTF(_WARN,__wine_dbch___default)
|
||||
#define WINE_WARN_(ch) __WINE_DPRINTF(_WARN,__wine_dbch_##ch)
|
||||
#define WINE_WARN_(ch) __WINE_DPRINTF(_WARN,&__wine_dbch_##ch)
|
||||
#endif
|
||||
#define WINE_WARN_ON(ch) __WINE_GET_DEBUGGING(_WARN,__wine_dbch_##ch)
|
||||
#define WINE_WARN_ON(ch) __WINE_GET_DEBUGGING(_WARN,&__wine_dbch_##ch)
|
||||
|
||||
#ifndef WINE_FIXME
|
||||
#define WINE_FIXME __WINE_DPRINTF(_FIXME,__wine_dbch___default)
|
||||
#define WINE_FIXME_(ch) __WINE_DPRINTF(_FIXME,__wine_dbch_##ch)
|
||||
#define WINE_FIXME_(ch) __WINE_DPRINTF(_FIXME,&__wine_dbch_##ch)
|
||||
#endif
|
||||
#define WINE_FIXME_ON(ch) __WINE_GET_DEBUGGING(_FIXME,__wine_dbch_##ch)
|
||||
#define WINE_FIXME_ON(ch) __WINE_GET_DEBUGGING(_FIXME,&__wine_dbch_##ch)
|
||||
|
||||
#define WINE_ERR __WINE_DPRINTF(_ERR,__wine_dbch___default)
|
||||
#define WINE_ERR_(ch) __WINE_DPRINTF(_ERR,__wine_dbch_##ch)
|
||||
#define WINE_ERR_ON(ch) __WINE_GET_DEBUGGING(_ERR,__wine_dbch_##ch)
|
||||
#define WINE_ERR_(ch) __WINE_DPRINTF(_ERR,&__wine_dbch_##ch)
|
||||
#define WINE_ERR_ON(ch) __WINE_GET_DEBUGGING(_ERR,&__wine_dbch_##ch)
|
||||
|
||||
#define WINE_DECLARE_DEBUG_CHANNEL(ch) \
|
||||
extern char __wine_dbch_##ch[]
|
||||
extern struct __wine_debug_channel __wine_dbch_##ch
|
||||
#define WINE_DEFAULT_DEBUG_CHANNEL(ch) \
|
||||
extern char __wine_dbch_##ch[]; \
|
||||
static char * const __wine_dbch___default = __wine_dbch_##ch
|
||||
extern struct __wine_debug_channel __wine_dbch_##ch; \
|
||||
static struct __wine_debug_channel * const __wine_dbch___default = &__wine_dbch_##ch
|
||||
|
||||
#define WINE_DPRINTF wine_dbg_printf
|
||||
#define WINE_MESSAGE wine_dbg_printf
|
||||
|
|
|
@ -58,13 +58,6 @@ extern void wine_init( int argc, char *argv[], char *error, int error_size );
|
|||
|
||||
/* debugging */
|
||||
|
||||
extern const char * (*__wine_dbgstr_an)( const char * s, int n );
|
||||
extern const char * (*__wine_dbgstr_wn)( const WCHAR *s, int n );
|
||||
extern const char * (*__wine_dbg_vsprintf)( const char *format, va_list args );
|
||||
extern int (*__wine_dbg_vprintf)( const char *format, va_list args );
|
||||
extern int (*__wine_dbg_vlog)( unsigned int cls, const char *channel,
|
||||
const char *function, const char *format, va_list args );
|
||||
|
||||
extern void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear );
|
||||
extern int wine_dbg_parse_options( const char *str );
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ struct dll
|
|||
{
|
||||
struct dll *next; /* linked list of dlls */
|
||||
struct dll *prev;
|
||||
char * const *channels; /* array of channels */
|
||||
struct __wine_debug_channel * const *channels; /* array of channels */
|
||||
int nb_channels; /* number of channels in array */
|
||||
};
|
||||
|
||||
|
@ -51,14 +51,15 @@ struct debug_option
|
|||
|
||||
static struct debug_option *first_option;
|
||||
static struct debug_option *last_option;
|
||||
static struct __wine_debug_functions funcs;
|
||||
|
||||
static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" };
|
||||
|
||||
static int cmp_name( const void *p1, const void *p2 )
|
||||
{
|
||||
const char *name = p1;
|
||||
const char * const *chan = p2;
|
||||
return strcmp( name, *chan + 1 );
|
||||
const struct __wine_debug_channel * const *chan = p2;
|
||||
return strcmp( name, (*chan)->name );
|
||||
}
|
||||
|
||||
/* apply a debug option to the channels of a given dll */
|
||||
|
@ -66,20 +67,20 @@ static void apply_option( struct dll *dll, const struct debug_option *opt )
|
|||
{
|
||||
if (opt->name[0])
|
||||
{
|
||||
char **dbch = bsearch( opt->name, dll->channels, dll->nb_channels,
|
||||
sizeof(*dll->channels), cmp_name );
|
||||
if (dbch) **dbch = (**dbch & ~opt->clear) | opt->set;
|
||||
struct __wine_debug_channel * const *dbch = bsearch( opt->name, dll->channels, dll->nb_channels,
|
||||
sizeof(*dll->channels), cmp_name );
|
||||
if (dbch) (*dbch)->flags = ((*dbch)->flags & ~opt->clear) | opt->set;
|
||||
}
|
||||
else /* all */
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dll->nb_channels; i++)
|
||||
dll->channels[i][0] = (dll->channels[i][0] & ~opt->clear) | opt->set;
|
||||
dll->channels[i]->flags = (dll->channels[i]->flags & ~opt->clear) | opt->set;
|
||||
}
|
||||
}
|
||||
|
||||
/* register a new set of channels for a dll */
|
||||
void *__wine_dbg_register( char * const *channels, int nb )
|
||||
void *__wine_dbg_register( struct __wine_debug_channel * const *channels, int nb )
|
||||
{
|
||||
struct debug_option *opt = first_option;
|
||||
struct dll *dll = malloc( sizeof(*dll) );
|
||||
|
@ -204,7 +205,7 @@ int wine_dbg_printf( const char *format, ... )
|
|||
va_list valist;
|
||||
|
||||
va_start(valist, format);
|
||||
ret = __wine_dbg_vprintf( format, valist );
|
||||
ret = funcs.dbg_vprintf( format, valist );
|
||||
va_end(valist);
|
||||
return ret;
|
||||
}
|
||||
|
@ -217,20 +218,21 @@ const char *wine_dbg_sprintf( const char *format, ... )
|
|||
va_list valist;
|
||||
|
||||
va_start(valist, format);
|
||||
ret = __wine_dbg_vsprintf( format, valist );
|
||||
ret = funcs.dbg_vsprintf( format, valist );
|
||||
va_end(valist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* varargs wrapper for __wine_dbg_vlog */
|
||||
int wine_dbg_log( unsigned int cls, const char *channel, const char *func, const char *format, ... )
|
||||
int wine_dbg_log( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
|
||||
const char *func, const char *format, ... )
|
||||
{
|
||||
int ret;
|
||||
va_list valist;
|
||||
|
||||
va_start(valist, format);
|
||||
ret = __wine_dbg_vlog( cls, channel, func, format, valist );
|
||||
ret = funcs.dbg_vlog( cls, channel, func, format, valist );
|
||||
va_end(valist);
|
||||
return ret;
|
||||
}
|
||||
|
@ -372,46 +374,50 @@ static int default_dbg_vprintf( const char *format, va_list args )
|
|||
|
||||
|
||||
/* default implementation of wine_dbg_vlog */
|
||||
static int default_dbg_vlog( unsigned int cls, const char *channel, const char *func,
|
||||
const char *format, va_list args )
|
||||
static int default_dbg_vlog( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
|
||||
const char *func, const char *format, va_list args )
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (cls < sizeof(debug_classes)/sizeof(debug_classes[0]))
|
||||
ret += wine_dbg_printf( "%s:%s:%s ", debug_classes[cls], channel + 1, func );
|
||||
ret += wine_dbg_printf( "%s:%s:%s ", debug_classes[cls], channel->name, func );
|
||||
if (format)
|
||||
ret += __wine_dbg_vprintf( format, args );
|
||||
ret += funcs.dbg_vprintf( format, args );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* exported function pointers so that debugging functions can be redirected at run-time */
|
||||
|
||||
const char * (*__wine_dbgstr_an)( const char * s, int n ) = default_dbgstr_an;
|
||||
const char * (*__wine_dbgstr_wn)( const WCHAR *s, int n ) = default_dbgstr_wn;
|
||||
const char * (*__wine_dbg_vsprintf)( const char *format, va_list args ) = default_dbg_vsprintf;
|
||||
int (*__wine_dbg_vprintf)( const char *format, va_list args ) = default_dbg_vprintf;
|
||||
int (*__wine_dbg_vlog)( unsigned int cls, const char *channel, const char *function,
|
||||
const char *format, va_list args ) = default_dbg_vlog;
|
||||
|
||||
/* wrappers to use the function pointers */
|
||||
|
||||
const char *wine_dbgstr_an( const char * s, int n )
|
||||
{
|
||||
return __wine_dbgstr_an(s, n);
|
||||
return funcs.dbgstr_an(s, n);
|
||||
}
|
||||
|
||||
const char *wine_dbgstr_wn( const WCHAR *s, int n )
|
||||
{
|
||||
return __wine_dbgstr_wn(s, n);
|
||||
return funcs.dbgstr_wn(s, n);
|
||||
}
|
||||
|
||||
const char *wine_dbgstr_a( const char *s )
|
||||
{
|
||||
return __wine_dbgstr_an( s, -1 );
|
||||
return funcs.dbgstr_an( s, -1 );
|
||||
}
|
||||
|
||||
const char *wine_dbgstr_w( const WCHAR *s )
|
||||
{
|
||||
return __wine_dbgstr_wn( s, -1 );
|
||||
return funcs.dbgstr_wn( s, -1 );
|
||||
}
|
||||
|
||||
void __wine_dbg_set_functions( const struct __wine_debug_functions *new_funcs, size_t size )
|
||||
{
|
||||
memcpy( &funcs, new_funcs, min(sizeof(funcs),size) );
|
||||
}
|
||||
|
||||
static struct __wine_debug_functions funcs =
|
||||
{
|
||||
default_dbgstr_an,
|
||||
default_dbgstr_wn,
|
||||
default_dbg_vsprintf,
|
||||
default_dbg_vprintf,
|
||||
default_dbg_vlog
|
||||
};
|
||||
|
|
|
@ -2,12 +2,8 @@ LIBRARY libwine.dll
|
|||
|
||||
EXPORTS
|
||||
__wine_dbg_register
|
||||
__wine_dbg_set_functions
|
||||
__wine_dbg_unregister
|
||||
__wine_dbg_vlog
|
||||
__wine_dbg_vprintf
|
||||
__wine_dbg_vsprintf
|
||||
__wine_dbgstr_an
|
||||
__wine_dbgstr_wn
|
||||
__wine_dll_register
|
||||
__wine_main_argc
|
||||
__wine_main_argv
|
||||
|
|
|
@ -2,12 +2,8 @@ WINE_1.0
|
|||
{
|
||||
global:
|
||||
__wine_dbg_register;
|
||||
__wine_dbg_set_functions;
|
||||
__wine_dbg_unregister;
|
||||
__wine_dbg_vlog;
|
||||
__wine_dbg_vprintf;
|
||||
__wine_dbg_vsprintf;
|
||||
__wine_dbgstr_an;
|
||||
__wine_dbgstr_wn;
|
||||
__wine_dll_register;
|
||||
__wine_main_argc;
|
||||
__wine_main_argv;
|
||||
|
|
|
@ -56,14 +56,17 @@ static int output_debug( FILE *outfile )
|
|||
if (!nb_debug_channels) return 0;
|
||||
qsort( debug_channels, nb_debug_channels, sizeof(debug_channels[0]), string_compare );
|
||||
|
||||
fprintf( outfile, "#include \"wine/debug.h\"\n\n" );
|
||||
|
||||
for (i = 0; i < nb_debug_channels; i++)
|
||||
fprintf( outfile, "char __wine_dbch_%s[] = \"\\003%s\";\n",
|
||||
fprintf( outfile, "struct __wine_debug_channel __wine_dbch_%s = { 3, \"%s\" };\n",
|
||||
debug_channels[i], debug_channels[i] );
|
||||
|
||||
fprintf( outfile, "\nstatic char * const debug_channels[%d] =\n{\n", nb_debug_channels );
|
||||
fprintf( outfile, "\nstatic struct __wine_debug_channel * const debug_channels[%d] =\n{\n",
|
||||
nb_debug_channels );
|
||||
for (i = 0; i < nb_debug_channels; i++)
|
||||
{
|
||||
fprintf( outfile, " __wine_dbch_%s", debug_channels[i] );
|
||||
fprintf( outfile, " &__wine_dbch_%s", debug_channels[i] );
|
||||
if (i < nb_debug_channels - 1) fprintf( outfile, ",\n" );
|
||||
}
|
||||
fprintf( outfile, "\n};\n\n" );
|
||||
|
@ -647,7 +650,7 @@ void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv )
|
|||
fprintf( outfile,
|
||||
"void %s(void)\n"
|
||||
"{\n"
|
||||
" extern void *__wine_dbg_register( char * const *, int );\n"
|
||||
" extern void *__wine_dbg_register( struct __wine_debug_channel * const *, int );\n"
|
||||
" if (!debug_registration) debug_registration = __wine_dbg_register( debug_channels, %d );\n"
|
||||
"}\n\n", constructor, nr_debug );
|
||||
fprintf( outfile,
|
||||
|
|
Loading…
Reference in New Issue