In the last chapter it was pointed out that a libgdb application is responsible for providing commands for the interpreter to execute. However some commands require further input (for example, the "quit" command might ask for confirmation). Almost all commands produce output of some kind. The purpose of this section is to explain how libgdb performs its I/O, and how an application can take advantage of this.
Libgdb has no fixed strategy for I/O. Instead, all operations are performed by functions called via structures of function pointers. Applications supply theses structures and can change them at any time.
The application allocates these structures, initializes them to all bits zero, fills in the function pointers, and then registers names for them them with libgdb.
char * name; struct gdb_output_vector * vec;
These functions are used to give and remove names to i/o vectors. Note that if a name is used twice, the most recent definition applies.
An output vector is a structure with at least these fields:
struct gdb_output_vector { /* output */ void (*put_string) (struct gdb_output_vector *, char * str); }
Use the function memset
or something equivalent to initialize an
output vector to all bits zero. Then fill in the function pointer with
your function.
A debugger command can produce three kinds of output: error messages (such as when trying to delete a non-existent breakpoint), informational messages (such as the notification printed when a breakpoint is hit), and the output specifically requested by a command (for example, the value printed by the "print" command). At any given time, then, libgdb has three output vectors. These are called the error, info, value vector respectively.
struct gdb_input_vector { int (*query) (struct gdb_input_vector *, char * prompt, int quit_allowed); int * (*selection) (struct gdb_input_vector *, char * prompt, char ** choices); char * (*read_string) (struct gdb_input_vector *, char * prompt); char ** (*read_strings) (struct gdb_input_vector *, char * prompt); }
Use the function memset
or something equivalent to initialize an
input vector to all bits zero. Then fill in the function pointers with
your functions.
There are four kinds of input requests explicitly made by libgdb.
A query is a yes or no question. The user can respond to a query with an affirmative or negative answer, or by telling gdb to abort the command (in some cases an abort is not permitted). Query should return 'y' or 'n' or 0 to abort.
A selection is a list of options from which the user selects a subset.
Selections should return a NULL terminated array of integers, which are
indexes into the array of choices. It can return NULL instead to abort
the command. The array returned by this function will be passed to
free
by libgdb.
A read_string asks the user to supply an arbitrary string. It may
return NULL to abort the command. The string returned by read_string
should be allocated by malloc
; it will be freed by libgdb.
A read_strings asks the user to supply multiple lines of input (for example, the body of a command created using `define'). It, too, may return NULL to abort. The array and the strings returned by this function will be freed by libgdb.
struct gdb_io_vecs { struct gdb_input_vector * input; struct gdb_output_vector * error; struct gdb_output_vector * info; struct gdb_output_vector * value; }
This establishes a new set of i/o vectors, and returns the old setting. Any of the pointers in this structure may be NULL, indicating that the current value should be used.
This function is useful for setting up i/o vectors before any libgdb commands have been invoked (hence before any input or output has taken place).
It is explained in a later chapter how to redirect output temporarily. (See section Invoking the Interpreter, Executing Commands.)
A libgdb application creates input and output vectors and assigns them names. Which input and output vectors are used by libgdb is established by executing these debugger commands:
A few debugger commands are for use only within commands defined using the debugger command `define' (they have no effect at other times). These commands exist so that an application can maintain hooks which redirect output without affecting the global I/O vectors.
When libgdb is initialized, a set of default I/O vectors is put in
place. The default vectors are called default-input-vector
,
default-output-vector
, &c.
The default query function always returns `y'. Other input functions always abort. The default output functions discard output silently.
Go to the first, previous, next, last section, table of contents.