Go to the first, previous, next, last section, table of contents.


How the Server's I/O Can be Used

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.

I/O Vectors

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.

Type: struct gdb_input_vector
Type: struct gdb_output_vector
These structures contain a set of function pointers. Each function determines how a particular type of i/o is performed. The details of these strucutres are explained below.

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.

Function: void gdb_name_input_vector (name, vec)
Function: void gdb_remove_input_vector (name, vec)
Function: void gdb_name_output_vector (name, vec)
Function: void gdb_remove_input_vector (name, vec)
  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.

Output

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.

Input

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.

I/O Redirection from the Application Top-Level

Function: struct gdb_io_vecs gdb_set_io (struct gdb_io_vecs *)
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.)

I/O Redirection in Debugger 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:

Function: set input-vector name
Function: set error-output-vector name
Function: set info-output-vector name
Function: set value-output-vector name
Choose an I/O vector by name.

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.

Function: with-input-vector name
Function: with-error-output-vector name
Function: with-info-output-vector name
Function: with-value-output-vector name
Set an I/O vector, but only temporarily. The setting has effect only within the command definition in which it occurs.

Initial Conditions

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.