[rfc/mi] ui_list_* to ui_*

Fernando Nasser fnasser@redhat.com
Sat Mar 24 07:43:00 GMT 2001


Eli,

This is what I wrote originally.  I had the impression that Andrew had a
revised/edited version of this, but I may be mistaken.

The text below does not reflect the changes that Andrew has posted (he
must add the doc part to the patch).


GUIDE TO UI_OUT FUNCTIONS
=========================


A FEW DEFINITIONS

The execution of gdb commands generally produces some sort of output
and can even generate an input request.

Output can be generated as: 

  ."result" of an operation;

  ."info", or side-effects of a requested operation;

  ."notification" of an asynchronous event (including the progress of
   a slow asynchronous operation);

  ."error" messages (including warnings);

  ."debug" data;

  ."query prompts" (a special case).

This document concentrates on how to build result output, although some
of it also applies to other kinds of output.

Result output generated usually includes some of the following:

  .the actual data;

  .console output formatting (to make it user readable);

  .machine oriented formatting (a more terse formatting for easy of
parsing);

  .annotation for helping a GUI (or emacs) to identify interesting
   parts of a console formatted output.

The ui_out routines take care of the first three cases.  Annotation is
done by separate annotation routines.  Use of annotation as a GUI to
gdb interface is deprecated.

Output can be in the form of a single item, which we call "field", a
list of fields or a table (which is a list of a list of fields with a
header).  In a BNF-like form:

<field> ::= any single item of data kept by gdb ;;

<list> ::= { <field> } ;;

<table> ::= <header> { <list> } ;;

<header> ::= { <column> } ;;

<column> ::= <width> <alignment> <title> ;;



GENERAL INFORMATION

All ui_out routines currently are of type "void", except for
ui_out_stream_new() which returns a pointer to the new object created.

The first parameter is always the ui_out vector object.

The "format" parameter is like in printf.  When it is present, there
is usually also a variable list of arguments used to complete the %
entries
in that.

When a character string argument is not used in a ui_out function
call, a NULL pointer has to be supplied instead.


TABLE AND LIST FUNCTIONS

This section introduces ui_out routines to build lists and tables.
The routines to output the actual data items (fields) are presented in
the next section.

A list is a sequence of fields with information about an object.

A table is a list of lists, each on a separate line, prefixed by a
header line with the column titles.

Use the table functions if your output is composed of a list of fields
for several objects and the console output shall have a header.  Use
this even when you are listing just one object but you still want the
header.

Use the list functions for the output of each object of a table or if
your output consists of a single list of fields.

You can nest a list into a table but not the opposite.

Lists can be nested (some of your fields may be a list (or
a tuple), like a {name,value} pair).  The maximum nesting level is
currently 4.

Function descriptions:

ui_out_table_begin (uiout, nbrofcols, tblid)

  nbrofcols - number of columns in the table.
  tblid - an optional string identifying the table
  
ui_out_table_header (uiout, width, alignment, colhdr)

  width - column width in chars.
  alignment - {left, center, right}
  colhdr - column header string

ui_out_table_body (uiout)

ui_out_table_end (uiout)

The functions ui_out_table_begin() and ui_out_table_end() are to be
used as brackets around output code that generated table data. The
calls to ui_out_table_header() must follow the call to
ui_out_table_begin() and precede ui_out_table_body(). The lists that
represent the table rows must follow the ui_out_table_begin() call and
precede the call to ui_out_table_end().


ui_out_list_begin (uiout, lstid)

  listid - an optional string identifying the list

ui_out_list_end (uiout)


These functions are to be used as brackets around code that produce
the actual list output.  A listheader can be supplied and will precede
the list fields.


Thus, the structure of the table output code is something like:

  ui_out_table_begin
    ui_out_table_header
    ...
  ui_out_table_body
    ui_out_list_begin
      ui_out_field_*
      ...
    ui_out_list_end
    ...
  ui_out_table_end



ITEM OUTPUT FUNCTIONS

These are the functions that produce output with the actual data
items, or fields, which contain information about the object.

Choose the appropriate function accordingly to your particular needs.


ui_out_field_fmt (uiout, fldname, format, ...)

  fldname - name of the field.
  format - format string (like in printf) to display the field data.
  ... - variable list.

Use ui_out_field_fmt() for elements of a list.  It can also be used for
single item output, if it is generated in a single call.  This generic
function should be used only when it is not possible to use one of the
specialized versions (see below). 

ui_out_field_int (uiout, fldname, value)

Specialized version of ui_out_field() for int variables.  It assumes a
"%d" output conversion specification.

ui_out_field_core_addr (uiout, fldname, address)

Specialized version of ui_out_field() which correctly handles
CORE_ADDR.

ui_out_field_string (uiout, fldname, string)

Specialized version of ui_out_field() for strings.  It assumes a "%s"
output conversion specification.


streambuffer = ui_out_stream_new (uiout)

ui_out_stream_delete (streambuffer)

ui_out_field_stream (uiout, fieldname, streambuffer)

Use these functions if you have to compose your output piece by piece,
using fprintf_stream() or fputc_stream() lower level routines.  Just
pass the stream created by ui_out_stream_new(), streambuffer->stream,
(you have to declare the pointer somewhere) to these routines and the
output is accumulated.

ui_out_field_stream() grabs all data so far accumulated and works like
ui_out_field_string() for all other purposes.  Calling
ui_out_field_stream()
frees the accumulated string (i.e., the data in the buffer is consumed)
but not the stream descriptor.  When it is no longer necessary, you must
call ui_out_stream_delete() to deallocate the memory.

Important: If there is any chance the current function will bail out
before
completing and reaching the point where ui_out_stream_delete() is
called,
it is necessary to set a cleanup.  You can do it as follows:
  mybuf = ui_out_stream_new (uiout);
  old_cleanup = make_cleanup (ui_out_stream_delete, mybuf);
  ...
  do_cleanup (old_cleanup);
If the function already has the old_cleanup part set, you just have to
add:
  mybuf = ui_out_stream_new (uiout);
  make_cleanup (ui_out_stream_delete, mybuf);
Note that with cleanups in place, you should not call
ui_out_stream_delete()
directly or you would attempt to free the same buffer twice.


ui_out_field_skip (uiout, fieldname)

Use this one if you have to ommit a field in a table, so that the
columns
are handled correctly.


ui_out_text (uiout, string)

  string - string to be used for human readability.

ui_out_spaces (uiout, numspaces)

  numspaces - number of spaces to include in the current output
location.

The above functions are used to insert text around the actual field
data for readability.  This is important if the output is to be
displayed at the console, for instance, or if it will be displayed in
an unmodified form by the GUI.


ui_out_message (uiout, verbosity, format, ...)

  verbosity - indicates the minimum verbosity level required for this
              information to be displayed.

Used to generate free format messages.


ui_out_wrap_hint (uiout, identstring)

This gives the console output filter (paging filter) a hint of where
to break lines which are too long.  Ignored for all other output
consumers.


ui_out_flush (uiout)

Flushes whatever output has been accumulated so far in UIs that buffer
output.


EXAMPLES OF USE OF UI_OUT FUNCTIONS
===================================

On breakpoints.c  breakpoint_1()

Was:

        if (!found_a_breakpoint++)
          {
            annotate_breakpoints_headers ();

            annotate_field (0);
            printf_filtered ("Num ");
            annotate_field (1);
            printf_filtered ("Type           ");
            annotate_field (2);
            printf_filtered ("Disp ");
            annotate_field (3);
            printf_filtered ("Enb ");
            if (addressprint)
              {
                annotate_field (4);
                printf_filtered ("Address    ");
              }
            annotate_field (5);
            printf_filtered ("What\n");

            annotate_breakpoints_table ();
          }

Became:

        if (!found_a_breakpoint++)
          {
            annotate_breakpoints_headers ();
            if (addressprint)
              ui_out_table_begin (ui, 6);
            else
              ui_out_table_begin (ui, 5);

            annotate_field (0);
            ui_out_table_header (ui, 4, left, "Num");
            annotate_field (1);
            ui_out_table_header (ui, 15, left, "Type");
            annotate_field (2);
            ui_out_table_header (ui, 5, left, "Disp");
            annotate_field (3);
            ui_out_table_header (ui, 4, left, "Enb");
            if (addressprint)
              {
                annotate_field (4);
                ui_out_table_header (ui, 11, left, "Address");
              }
            annotate_field (5);
            ui_out_table_header (ui, 40, left, "What");

            ui_out_table_body (ui);
            annotate_breakpoints_table ();
          }


Was:

        annotate_record ();
        annotate_field (0);
        printf_filtered ("%-3d ", b->number);
        annotate_field (1);
        if ((int)b->type > (sizeof(bptypes)/sizeof(bptypes[0])))
          error ("bptypes table does not describe type #%d.",
(int)b->type);
        if ((int)b->type != bptypes[(int)b->type].type)
          error ("bptypes table does not describe type #%d?",
(int)b->type);
        printf_filtered ("%-14s ", bptypes[(int)b->type].description);
        annotate_field (2);
        printf_filtered ("%-4s ", bpdisps[(int)b->disposition]);
        annotate_field (3);
        printf_filtered ("%-3c ", bpenables[(int)b->enable]);

Became:

        annotate_record ();
        ui_out_list_begin (ui, 0);
        annotate_field (0);
        ui_out_field_int (ui, "Number", b->number);
        ui_out_spaces (ui, 1);
        annotate_field (1);
        if ((int)b->type > (sizeof(bptypes)/sizeof(bptypes[0])))
          error ("bptypes table does not describe type #%d.",
(int)b->type);
        if ((int)b->type != bptypes[(int)b->type].type)
          error ("bptypes table does not describe type #%d?",
(int)b->type);
        ui_out_field_string (ui, "Type",
bptypes[(int)b->type].description);
        ui_out_spaces (ui, 1);
        annotate_field (2);
        ui_out_field_string (ui, "Disp", bpdisps[(int)b->disposition]);
        ui_out_spaces (ui, 1);
        annotate_field (3);
        ui_out_field_fmt (ui, "Enabled", "%c",
bpenables[(int)b->enable]);
        ui_out_spaces (ui, 3);


Was:

            annotate_field (5);
            print_expression (b->exp, gdb_stdout);

Became:

            GDB_FILE *local_stream;

            annotate_field (5);
            ui_out_newstream (ui, &local_stream);
            print_expression (b->exp, local_stream);
            ui_out_field_stream (ui, "What", local_stream);
            ui_out_destroystream (ui, &local_stream);

Was:

            annotate_field (5);
            if (b->dll_pathname == NULL)
              printf_filtered ("<any library> ");
            else
              printf_filtered ("library \"%s\" ", b->dll_pathname);

Became:

            annotate_field (5);
            if (b->dll_pathname == NULL)
              {
                ui_out_field_string (ui, "What", "<any library>");
                ui_out_spaces (ui, 1);
              }
            else
              {
                ui_out_padding ("library \"");
                ui_out_field_string (ui, "What", b->dll_pathname);
                ui_out_padding ("\" ");
              }


Was:

            annotate_field (5);
            if (b->forked_inferior_pid != 0)
              printf_filtered ("process %d ", b->forked_inferior_pid);

Became:

            annotate_field (5);
            if (b->forked_inferior_pid != 0)
              {
                ui_out_padding ("process ");
                ui_out_field_int (ui, "What", b->forked_inferior_pid);
                ui_out_spaces (ui, 1);
              }

Was:

            annotate_field (5);
            if (b->exec_pathname != NULL)
              printf_filtered ("program \"%s\" ", b->exec_pathname);

Became:

            annotate_field (5);
            if (b->exec_pathname != NULL)
              {
                ui_out_padding ("program \"");
                ui_out_field_string (ui, "What", b->exec_pathname);
                ui_out_padding ("\" ");
              }

Was:

            annotate_field (5);
            printf_filtered ("exception catch ");

Became:

            annotate_field (5);
            ui_out_field_string (ui, "What", "exception catch");
            ui_out_spaces (ui, 1);

Was:
            annotate_field (5);
            printf_filtered ("exception throw ");

Became:

            annotate_field (5);
            ui_out_field_string (ui, "What", "exception throw");
            ui_out_spaces (ui, 1);

Was:

                annotate_field (4);
                /* FIXME-32x64: need a print_address_numeric with
                   field width */
                printf_filtered
                  ("%s ",
                   local_hex_string_custom
                   ((unsigned long) b->address, "08l"));

Became:

                annotate_field (4);
                ui_out_field_core_addr (ui, "Address", b->address);
                ui_out_spaces (ui, 1);




-- 
Fernando Nasser
Red Hat Canada Ltd.                     E-Mail:  fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario   M4P 2C9



More information about the Gdb-patches mailing list