* linux-nat.c (debug_linux_nat_async): Delete.
Replace all references to use debug_linux_nat instead. (show_debug_linux_nat_async): Delete. (sigchld_handler): Call ui_file_write_async_safe instead of fprintf_unfiltered. (_initialize_linux_nat): Remove `set debug lin-lwp-async'. * ui-file.c (struct ui_file): New member to_write_async_safe. (null_file_write_async_safe): New function. (ui_file_write_async_safe): New function. (set_ui_file_write_async_safe): New function. (ui_file_new): Initialize to_write_async_safe. (stdio_file_write_async_safe): New function. (struct stdio_file): New member fd. (stdio_file_new): Initialize to_write_async_safe, fd. (stdio_file_read, stdio_file_isatty): New stdio->fd instead of calling fileno. * ui-file.h (ui_file_write_async_safe_ftype): New typedef. (set_ui_file_write_async_safe): Declare. (ui_file_write_async_safe): Declare. doc/ * gdb.texinfo (Completion): Update example. (Debugging Output): Delete `set/show debug lin-lwp-async'.
This commit is contained in:
parent
6edba76fe8
commit
01124a23b3
6 changed files with 107 additions and 40 deletions
|
@ -1,3 +1,24 @@
|
||||||
|
2011-05-13 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
|
* linux-nat.c (debug_linux_nat_async): Delete.
|
||||||
|
Replace all references to use debug_linux_nat instead.
|
||||||
|
(show_debug_linux_nat_async): Delete.
|
||||||
|
(sigchld_handler): Call ui_file_write_async_safe instead of
|
||||||
|
fprintf_unfiltered.
|
||||||
|
(_initialize_linux_nat): Remove `set debug lin-lwp-async'.
|
||||||
|
* ui-file.c (struct ui_file): New member to_write_async_safe.
|
||||||
|
(null_file_write_async_safe): New function.
|
||||||
|
(ui_file_write_async_safe): New function.
|
||||||
|
(set_ui_file_write_async_safe): New function.
|
||||||
|
(ui_file_new): Initialize to_write_async_safe.
|
||||||
|
(stdio_file_write_async_safe): New function.
|
||||||
|
(struct stdio_file): New member fd.
|
||||||
|
(stdio_file_new): Initialize to_write_async_safe, fd.
|
||||||
|
(stdio_file_read, stdio_file_isatty): New stdio->fd instead of calling fileno.
|
||||||
|
* ui-file.h (ui_file_write_async_safe_ftype): New typedef.
|
||||||
|
(set_ui_file_write_async_safe): Declare.
|
||||||
|
(ui_file_write_async_safe): Declare.
|
||||||
|
|
||||||
2011-05-13 Tom Tromey <tromey@redhat.com>
|
2011-05-13 Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
* utils.c (do_value_free): New function.
|
* utils.c (do_value_free): New function.
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2011-05-13 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
|
* gdb.texinfo (Completion): Update example.
|
||||||
|
(Debugging Output): Delete `set/show debug lin-lwp-async'.
|
||||||
|
|
||||||
2011-05-12 Kwok Cheung Yeung <kcy@codesourcery.com>
|
2011-05-12 Kwok Cheung Yeung <kcy@codesourcery.com>
|
||||||
|
|
||||||
* gdb.texinfo: Document change in the behaviour of the enable and
|
* gdb.texinfo: Document change in the behaviour of the enable and
|
||||||
|
|
|
@ -1592,8 +1592,10 @@ left-hand-side:
|
||||||
|
|
||||||
@smallexample
|
@smallexample
|
||||||
(@value{GDBP}) p gdb_stdout.@kbd{M-?}
|
(@value{GDBP}) p gdb_stdout.@kbd{M-?}
|
||||||
magic to_delete to_fputs to_put to_rewind
|
magic to_fputs to_rewind
|
||||||
to_data to_flush to_isatty to_read to_write
|
to_data to_isatty to_write
|
||||||
|
to_delete to_put to_write_async_safe
|
||||||
|
to_flush to_read
|
||||||
@end smallexample
|
@end smallexample
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
|
@ -1607,6 +1609,7 @@ struct ui_file
|
||||||
int *magic;
|
int *magic;
|
||||||
ui_file_flush_ftype *to_flush;
|
ui_file_flush_ftype *to_flush;
|
||||||
ui_file_write_ftype *to_write;
|
ui_file_write_ftype *to_write;
|
||||||
|
ui_file_write_async_safe_ftype *to_write_async_safe;
|
||||||
ui_file_fputs_ftype *to_fputs;
|
ui_file_fputs_ftype *to_fputs;
|
||||||
ui_file_read_ftype *to_read;
|
ui_file_read_ftype *to_read;
|
||||||
ui_file_delete_ftype *to_delete;
|
ui_file_delete_ftype *to_delete;
|
||||||
|
@ -20071,12 +20074,6 @@ Displays the current state of @value{GDBN} JIT debugging.
|
||||||
Turns on or off debugging messages from the Linux LWP debug support.
|
Turns on or off debugging messages from the Linux LWP debug support.
|
||||||
@item show debug lin-lwp
|
@item show debug lin-lwp
|
||||||
Show the current state of Linux LWP debugging messages.
|
Show the current state of Linux LWP debugging messages.
|
||||||
@item set debug lin-lwp-async
|
|
||||||
@cindex @sc{gnu}/Linux LWP async debug messages
|
|
||||||
@cindex Linux lightweight processes
|
|
||||||
Turns on or off debugging messages from the Linux LWP async debug support.
|
|
||||||
@item show debug lin-lwp-async
|
|
||||||
Show the current state of Linux LWP async debugging messages.
|
|
||||||
@item set debug observer
|
@item set debug observer
|
||||||
@cindex observer debugging info
|
@cindex observer debugging info
|
||||||
Turns on or off display of @value{GDBN} observer debugging. This
|
Turns on or off display of @value{GDBN} observer debugging. This
|
||||||
|
|
|
@ -198,16 +198,6 @@ show_debug_linux_nat (struct ui_file *file, int from_tty,
|
||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int debug_linux_nat_async = 0;
|
|
||||||
static void
|
|
||||||
show_debug_linux_nat_async (struct ui_file *file, int from_tty,
|
|
||||||
struct cmd_list_element *c, const char *value)
|
|
||||||
{
|
|
||||||
fprintf_filtered (file,
|
|
||||||
_("Debugging of GNU/Linux async lwp module is %s.\n"),
|
|
||||||
value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int disable_randomization = 1;
|
static int disable_randomization = 1;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -3260,7 +3250,7 @@ linux_nat_wait_1 (struct target_ops *ops,
|
||||||
int status = 0;
|
int status = 0;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
if (debug_linux_nat_async)
|
if (debug_linux_nat)
|
||||||
fprintf_unfiltered (gdb_stdlog, "LLW: enter\n");
|
fprintf_unfiltered (gdb_stdlog, "LLW: enter\n");
|
||||||
|
|
||||||
/* The first time we get here after starting a new inferior, we may
|
/* The first time we get here after starting a new inferior, we may
|
||||||
|
@ -3303,7 +3293,7 @@ retry:
|
||||||
{
|
{
|
||||||
ourstatus->kind = TARGET_WAITKIND_IGNORE;
|
ourstatus->kind = TARGET_WAITKIND_IGNORE;
|
||||||
|
|
||||||
if (debug_linux_nat_async)
|
if (debug_linux_nat)
|
||||||
fprintf_unfiltered (gdb_stdlog, "LLW: exit (no resumed LWP)\n");
|
fprintf_unfiltered (gdb_stdlog, "LLW: exit (no resumed LWP)\n");
|
||||||
|
|
||||||
restore_child_signals_mask (&prev_mask);
|
restore_child_signals_mask (&prev_mask);
|
||||||
|
@ -3546,7 +3536,7 @@ retry:
|
||||||
/* No interesting event. */
|
/* No interesting event. */
|
||||||
ourstatus->kind = TARGET_WAITKIND_IGNORE;
|
ourstatus->kind = TARGET_WAITKIND_IGNORE;
|
||||||
|
|
||||||
if (debug_linux_nat_async)
|
if (debug_linux_nat)
|
||||||
fprintf_unfiltered (gdb_stdlog, "LLW: exit (ignore)\n");
|
fprintf_unfiltered (gdb_stdlog, "LLW: exit (ignore)\n");
|
||||||
|
|
||||||
restore_child_signals_mask (&prev_mask);
|
restore_child_signals_mask (&prev_mask);
|
||||||
|
@ -3561,7 +3551,7 @@ retry:
|
||||||
/* No interesting event for PID yet. */
|
/* No interesting event for PID yet. */
|
||||||
ourstatus->kind = TARGET_WAITKIND_IGNORE;
|
ourstatus->kind = TARGET_WAITKIND_IGNORE;
|
||||||
|
|
||||||
if (debug_linux_nat_async)
|
if (debug_linux_nat)
|
||||||
fprintf_unfiltered (gdb_stdlog, "LLW: exit (ignore)\n");
|
fprintf_unfiltered (gdb_stdlog, "LLW: exit (ignore)\n");
|
||||||
|
|
||||||
restore_child_signals_mask (&prev_mask);
|
restore_child_signals_mask (&prev_mask);
|
||||||
|
@ -3690,7 +3680,7 @@ retry:
|
||||||
else
|
else
|
||||||
store_waitstatus (ourstatus, status);
|
store_waitstatus (ourstatus, status);
|
||||||
|
|
||||||
if (debug_linux_nat_async)
|
if (debug_linux_nat)
|
||||||
fprintf_unfiltered (gdb_stdlog, "LLW: exit\n");
|
fprintf_unfiltered (gdb_stdlog, "LLW: exit\n");
|
||||||
|
|
||||||
restore_child_signals_mask (&prev_mask);
|
restore_child_signals_mask (&prev_mask);
|
||||||
|
@ -5416,8 +5406,9 @@ sigchld_handler (int signo)
|
||||||
{
|
{
|
||||||
int old_errno = errno;
|
int old_errno = errno;
|
||||||
|
|
||||||
if (debug_linux_nat_async)
|
if (debug_linux_nat)
|
||||||
fprintf_unfiltered (gdb_stdlog, "sigchld\n");
|
ui_file_write_async_safe (gdb_stdlog,
|
||||||
|
"sigchld\n", sizeof ("sigchld\n") - 1);
|
||||||
|
|
||||||
if (signo == SIGCHLD
|
if (signo == SIGCHLD
|
||||||
&& linux_nat_event_pipe[0] != -1)
|
&& linux_nat_event_pipe[0] != -1)
|
||||||
|
@ -5801,15 +5792,6 @@ Enables printf debugging output."),
|
||||||
show_debug_linux_nat,
|
show_debug_linux_nat,
|
||||||
&setdebuglist, &showdebuglist);
|
&setdebuglist, &showdebuglist);
|
||||||
|
|
||||||
add_setshow_zinteger_cmd ("lin-lwp-async", class_maintenance,
|
|
||||||
&debug_linux_nat_async, _("\
|
|
||||||
Set debugging of GNU/Linux async lwp module."), _("\
|
|
||||||
Show debugging of GNU/Linux async lwp module."), _("\
|
|
||||||
Enables printf debugging output."),
|
|
||||||
NULL,
|
|
||||||
show_debug_linux_nat_async,
|
|
||||||
&setdebuglist, &showdebuglist);
|
|
||||||
|
|
||||||
/* Save this mask as the default. */
|
/* Save this mask as the default. */
|
||||||
sigprocmask (SIG_SETMASK, NULL, &normal_mask);
|
sigprocmask (SIG_SETMASK, NULL, &normal_mask);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
static ui_file_isatty_ftype null_file_isatty;
|
static ui_file_isatty_ftype null_file_isatty;
|
||||||
static ui_file_write_ftype null_file_write;
|
static ui_file_write_ftype null_file_write;
|
||||||
|
static ui_file_write_ftype null_file_write_async_safe;
|
||||||
static ui_file_fputs_ftype null_file_fputs;
|
static ui_file_fputs_ftype null_file_fputs;
|
||||||
static ui_file_read_ftype null_file_read;
|
static ui_file_read_ftype null_file_read;
|
||||||
static ui_file_flush_ftype null_file_flush;
|
static ui_file_flush_ftype null_file_flush;
|
||||||
|
@ -42,6 +43,7 @@ struct ui_file
|
||||||
int *magic;
|
int *magic;
|
||||||
ui_file_flush_ftype *to_flush;
|
ui_file_flush_ftype *to_flush;
|
||||||
ui_file_write_ftype *to_write;
|
ui_file_write_ftype *to_write;
|
||||||
|
ui_file_write_async_safe_ftype *to_write_async_safe;
|
||||||
ui_file_fputs_ftype *to_fputs;
|
ui_file_fputs_ftype *to_fputs;
|
||||||
ui_file_read_ftype *to_read;
|
ui_file_read_ftype *to_read;
|
||||||
ui_file_delete_ftype *to_delete;
|
ui_file_delete_ftype *to_delete;
|
||||||
|
@ -61,6 +63,7 @@ ui_file_new (void)
|
||||||
set_ui_file_data (file, NULL, null_file_delete);
|
set_ui_file_data (file, NULL, null_file_delete);
|
||||||
set_ui_file_flush (file, null_file_flush);
|
set_ui_file_flush (file, null_file_flush);
|
||||||
set_ui_file_write (file, null_file_write);
|
set_ui_file_write (file, null_file_write);
|
||||||
|
set_ui_file_write_async_safe (file, null_file_write_async_safe);
|
||||||
set_ui_file_fputs (file, null_file_fputs);
|
set_ui_file_fputs (file, null_file_fputs);
|
||||||
set_ui_file_read (file, null_file_read);
|
set_ui_file_read (file, null_file_read);
|
||||||
set_ui_file_isatty (file, null_file_isatty);
|
set_ui_file_isatty (file, null_file_isatty);
|
||||||
|
@ -154,6 +157,14 @@ null_file_fputs (const char *buf, struct ui_file *file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
null_file_write_async_safe (struct ui_file *file,
|
||||||
|
const char *buf,
|
||||||
|
long sizeof_buf)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
null_file_delete (struct ui_file *file)
|
null_file_delete (struct ui_file *file)
|
||||||
{
|
{
|
||||||
|
@ -203,6 +214,14 @@ ui_file_write (struct ui_file *file,
|
||||||
file->to_write (file, buf, length_buf);
|
file->to_write (file, buf, length_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ui_file_write_async_safe (struct ui_file *file,
|
||||||
|
const char *buf,
|
||||||
|
long length_buf)
|
||||||
|
{
|
||||||
|
file->to_write_async_safe (file, buf, length_buf);
|
||||||
|
}
|
||||||
|
|
||||||
long
|
long
|
||||||
ui_file_read (struct ui_file *file, char *buf, long length_buf)
|
ui_file_read (struct ui_file *file, char *buf, long length_buf)
|
||||||
{
|
{
|
||||||
|
@ -246,6 +265,13 @@ set_ui_file_write (struct ui_file *file,
|
||||||
file->to_write = write;
|
file->to_write = write;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_ui_file_write_async_safe (struct ui_file *file,
|
||||||
|
ui_file_write_async_safe_ftype *write_async_safe)
|
||||||
|
{
|
||||||
|
file->to_write_async_safe = write_async_safe;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_ui_file_read (struct ui_file *file, ui_file_read_ftype *read)
|
set_ui_file_read (struct ui_file *file, ui_file_read_ftype *read)
|
||||||
{
|
{
|
||||||
|
@ -437,6 +463,7 @@ mem_file_write (struct ui_file *file,
|
||||||
<stdio.h>'s FILE. */
|
<stdio.h>'s FILE. */
|
||||||
|
|
||||||
static ui_file_write_ftype stdio_file_write;
|
static ui_file_write_ftype stdio_file_write;
|
||||||
|
static ui_file_write_async_safe_ftype stdio_file_write_async_safe;
|
||||||
static ui_file_fputs_ftype stdio_file_fputs;
|
static ui_file_fputs_ftype stdio_file_fputs;
|
||||||
static ui_file_read_ftype stdio_file_read;
|
static ui_file_read_ftype stdio_file_read;
|
||||||
static ui_file_isatty_ftype stdio_file_isatty;
|
static ui_file_isatty_ftype stdio_file_isatty;
|
||||||
|
@ -450,6 +477,9 @@ struct stdio_file
|
||||||
{
|
{
|
||||||
int *magic;
|
int *magic;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
|
/* The associated file descriptor is extracted ahead of time for
|
||||||
|
stdio_file_write_async_safe's benefit, in case fileno isn't async-safe. */
|
||||||
|
int fd;
|
||||||
int close_p;
|
int close_p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -461,10 +491,12 @@ stdio_file_new (FILE *file, int close_p)
|
||||||
|
|
||||||
stdio->magic = &stdio_file_magic;
|
stdio->magic = &stdio_file_magic;
|
||||||
stdio->file = file;
|
stdio->file = file;
|
||||||
|
stdio->fd = fileno (file);
|
||||||
stdio->close_p = close_p;
|
stdio->close_p = close_p;
|
||||||
set_ui_file_data (ui_file, stdio, stdio_file_delete);
|
set_ui_file_data (ui_file, stdio, stdio_file_delete);
|
||||||
set_ui_file_flush (ui_file, stdio_file_flush);
|
set_ui_file_flush (ui_file, stdio_file_flush);
|
||||||
set_ui_file_write (ui_file, stdio_file_write);
|
set_ui_file_write (ui_file, stdio_file_write);
|
||||||
|
set_ui_file_write_async_safe (ui_file, stdio_file_write_async_safe);
|
||||||
set_ui_file_fputs (ui_file, stdio_file_fputs);
|
set_ui_file_fputs (ui_file, stdio_file_fputs);
|
||||||
set_ui_file_read (ui_file, stdio_file_read);
|
set_ui_file_read (ui_file, stdio_file_read);
|
||||||
set_ui_file_isatty (ui_file, stdio_file_isatty);
|
set_ui_file_isatty (ui_file, stdio_file_isatty);
|
||||||
|
@ -510,16 +542,14 @@ stdio_file_read (struct ui_file *file, char *buf, long length_buf)
|
||||||
the file. Wait until at least one byte of data is available.
|
the file. Wait until at least one byte of data is available.
|
||||||
Control-C can interrupt gdb_select, but not read. */
|
Control-C can interrupt gdb_select, but not read. */
|
||||||
{
|
{
|
||||||
int fd = fileno (stdio->file);
|
|
||||||
|
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
FD_ZERO (&readfds);
|
FD_ZERO (&readfds);
|
||||||
FD_SET (fd, &readfds);
|
FD_SET (stdio->fd, &readfds);
|
||||||
if (gdb_select (fd + 1, &readfds, NULL, NULL, NULL) == -1)
|
if (gdb_select (stdio->fd + 1, &readfds, NULL, NULL, NULL) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return read (fileno (stdio->file), buf, length_buf);
|
return read (stdio->fd, buf, length_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -535,6 +565,24 @@ stdio_file_write (struct ui_file *file, const char *buf, long length_buf)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stdio_file_write_async_safe (struct ui_file *file,
|
||||||
|
const char *buf, long length_buf)
|
||||||
|
{
|
||||||
|
struct stdio_file *stdio = ui_file_data (file);
|
||||||
|
|
||||||
|
if (stdio->magic != &stdio_file_magic)
|
||||||
|
{
|
||||||
|
/* gettext isn't necessarily async safe, so we can't use _("error message") here.
|
||||||
|
We could extract the correct translation ahead of time, but this is an extremely
|
||||||
|
rare event, and one of the other stdio_file_* routines will presumably catch
|
||||||
|
the problem anyway. For now keep it simple and ignore the error here. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write (stdio->fd, buf, length_buf);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stdio_file_fputs (const char *linebuffer, struct ui_file *file)
|
stdio_file_fputs (const char *linebuffer, struct ui_file *file)
|
||||||
{
|
{
|
||||||
|
@ -556,7 +604,7 @@ stdio_file_isatty (struct ui_file *file)
|
||||||
if (stdio->magic != &stdio_file_magic)
|
if (stdio->magic != &stdio_file_magic)
|
||||||
internal_error (__FILE__, __LINE__,
|
internal_error (__FILE__, __LINE__,
|
||||||
_("stdio_file_isatty: bad magic number"));
|
_("stdio_file_isatty: bad magic number"));
|
||||||
return (isatty (fileno (stdio->file)));
|
return (isatty (stdio->fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like fdopen(). Create a ui_file from a previously opened FILE. */
|
/* Like fdopen(). Create a ui_file from a previously opened FILE. */
|
||||||
|
|
|
@ -45,6 +45,17 @@ typedef void (ui_file_fputs_ftype) (const char *, struct ui_file *stream);
|
||||||
extern void set_ui_file_fputs (struct ui_file *stream,
|
extern void set_ui_file_fputs (struct ui_file *stream,
|
||||||
ui_file_fputs_ftype *fputs);
|
ui_file_fputs_ftype *fputs);
|
||||||
|
|
||||||
|
/* This version of "write" is safe for use in signal handlers.
|
||||||
|
It's not guaranteed that all existing output will have been
|
||||||
|
flushed first.
|
||||||
|
Implementations are also free to ignore some or all of the request.
|
||||||
|
fputs_async is not provided as the async versions are rarely used,
|
||||||
|
no point in having both for a rarely used interface. */
|
||||||
|
typedef void (ui_file_write_async_safe_ftype)
|
||||||
|
(struct ui_file *stream, const char *buf, long length_buf);
|
||||||
|
extern void set_ui_file_write_async_safe
|
||||||
|
(struct ui_file *stream, ui_file_write_async_safe_ftype *write_async_safe);
|
||||||
|
|
||||||
typedef long (ui_file_read_ftype) (struct ui_file *stream,
|
typedef long (ui_file_read_ftype) (struct ui_file *stream,
|
||||||
char *buf, long length_buf);
|
char *buf, long length_buf);
|
||||||
extern void set_ui_file_read (struct ui_file *stream,
|
extern void set_ui_file_read (struct ui_file *stream,
|
||||||
|
@ -83,6 +94,9 @@ extern int ui_file_isatty (struct ui_file *);
|
||||||
extern void ui_file_write (struct ui_file *file, const char *buf,
|
extern void ui_file_write (struct ui_file *file, const char *buf,
|
||||||
long length_buf);
|
long length_buf);
|
||||||
|
|
||||||
|
extern void ui_file_write_async_safe (struct ui_file *file, const char *buf,
|
||||||
|
long length_buf);
|
||||||
|
|
||||||
/* NOTE: copies left to right. */
|
/* NOTE: copies left to right. */
|
||||||
extern void ui_file_put (struct ui_file *src,
|
extern void ui_file_put (struct ui_file *src,
|
||||||
ui_file_put_method_ftype *write, void *dest);
|
ui_file_put_method_ftype *write, void *dest);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue