From 0ee5478628133b6daedb04d236dfde8e8abfe953 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 1 Apr 2001 09:07:08 +0000 Subject: [PATCH] * gdbint.texinfo (User Interface): A new section about ui_out functions, based on text written by Fernando Nasser. --- gdb/doc/ChangeLog | 3 + gdb/doc/gdbint.texinfo | 583 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 586 insertions(+) diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index a799d0371e2..8f4611f30c7 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,5 +1,8 @@ 2001-04-01 Eli Zaretskii + * gdbint.texinfo (User Interface): A new section about ui_out + functions, based on text written by Fernando Nasser. + * stabs.texinfo: Change Permissions to GFDL. Update Copyright. 2001-03-26 Eli Zaretskii diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 9be4ffb5222..7f8697d4cdb 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -717,6 +717,7 @@ is the most common and most familiar, there are others. @section Command Interpreter @cindex command interpreter +@cindex CLI The command interpreter in @value{GDBN} is fairly simple. It is designed to allow for the set of commands to be augmented dynamically, and also has a recursive subcommand capability, where the first argument to @@ -747,6 +748,588 @@ replacement (if one exists). Note that the replacement string passed to @code{deprecate_cmd} should be the full name of the command, i.e. the entire string the user should type at the command line. +@section UI-Independent Output---the @code{ui_out} Functions +@c This section is based on the documentation written by Fernando +@c Nasser . + +@cindex @code{ui_out} functions +The @code{ui_out} functions present an abstraction level for the +@value{GDBN} output code. They hide the specifics of different user +interfaces supported by @value{GDBN}, and thus free the programmer +from the need to write several versions of the same code, one each for +every UI, to produce output. + +@subsection Overview and Terminology + +In general, execution of each @value{GDBN} command produces some sort +of output, and can even generate an input request. + +Output can be generated for the following purposes: + +@itemize @bullet +@item +to display a @emph{result} of an operation; + +@item +to convey @emph{info} or produce side-effects of a requested +operation; + +@item +to provide a @emph{notification} of an asynchronous event (including +progress indication of a prolonged asynchronous operation); + +@item +to display @emph{error messages} (including warnings); + +@item +to show @emph{debug data}; + +@item +to @emph{query} or prompt a user for input (a special case). +@end itemize + +@noindent +This section mainly concentrates on how to build result output, +although some of it also applies to other kinds of output. + +Generation of output that displays the results of an operation +involves one or more of the following: + +@itemize @bullet +@item +output of the actual data + +@item +formatting the output as appropriate for console output, to make it +easily readable by humans + +@item +machine oriented formatting--a more terse formatting to allow for easy +parsing by programs which read @value{GDBN}'s output + +@item +annotation, whose purpose is to help a GUI (such as GDBTK or Emacs) to +identify interesting parts in the output +@end itemize + +The @code{ui_out} routines take care of the first three aspects. +Annotations are provided by separate annotation routines. Note that +use of annotations for an interface between a GUI and @value{GDBN} is +deprecated. + +Output can be in the form of a single item, which we call a +@dfn{field}; a @dfn{list} of fields; or a @dfn{table}, which is a list +of fields with a header. In a BNF-like form: + +@example + ::= any single item of data kept by gdb ;; + + ::= @{ @} ;; + + ::=
@{ @} ;; + +
::= @{ @} ;; + + ::= ;; +@end example + + +@subsection General Conventions + +All @code{ui_out} routines currently are of type @code{void}, except +for @code{ui_out_stream_new} which returns a pointer to the newly +created object. + +The first parameter is always the @code{ui_out} vector object, a +pointer to a @code{struct ui_out}. + +The @var{format} parameter is like in @code{printf} family of +functions. When it is present, there is usually also a variable list +of arguments used to satisfy the @code{%} specifiers in the supplied +format. + +When a character string argument is not used in a @code{ui_out} +function call, a @code{NULL} pointer has to be supplied instead. + + +@subsection Table and List Functions + +@cindex list output functions +@cindex table output functions +This section introduces @code{ui_out} routines for building lists and +tables. The routines to output the actual data items (fields) are +presented in the next section. + +To recap: A @dfn{list} is a sequence of @dfn{fields} with information +about an object; a @dfn{table} is a list of lists, each on a separate +line, prefixed by a @dfn{header} line with the column @dfn{titles}. + +Use the table functions if your output is composed of a list of fields +for several objects and the console output should 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 other way around. + +@cindex nesting level in @code{ui_out} functions +Lists can also be nested: some of your fields may be lists or +@dfn{tuples}--@code{@{@var{name},@var{value}@}} pairs. The maximum +nesting level is currently 4. + +The overall structure of the table output code is something like this: + +@example + 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 +@end example + +Here's the description of table- and list-related @code{ui_out} +functions: + +@deftypefun void ui_out_table_begin (struct ui_out *@var{uiout}, int @var{nbrofcols}, char *@var{tblid}) +The function @code{ui_out_table_begin} marks the beginning of the +output of a table. It should always be called before any other +@code{ui_out} function for a given table. @var{nbrofcols} is the +number of columns in the table, and @var{tblid} is an optional string +identifying the table. The string pointed to by @var{tblid} is copied +by the implementation of @code{ui_out_table_begin}, so the application +can free the string if it was @code{malloc}ed. + +The companion function @code{ui_out_table_end}, described below, marks +the end of the table's output. +@end deftypefun + +@deftypefun void ui_out_table_header (struct ui_out *@var{uiout}, int @var{width}, enum ui_align @var{alignment}, char *@var{colhdr}) +@code{ui_out_table_header} provides the header information for a +single table column. You call this function several times, one each +for every column of the table, after @code{ui_out_table_begin}, but +before @code{ui_out_table_body}. + +The value of @var{width} gives the column width in characters. The +value of @var{alignment} is one of @code{left}, @code{center}, and +@code{right}, and it specifies how to align the header: left-justify, +center, or right-justify it. @var{colhdr} points to a string that +specifies the column header; the implementation copies that string, so +column header strings in @code{malloc}ed storage can be freed after +the call. +@end deftypefun + +@deftypefun void ui_out_table_body (struct ui_out *@var{uiout}) +This function marks the end of header information and the beginning of +table body output. It doesn't by itself produce any data output; that +is done by the list and field output functions described below. +@end deftypefun + +@deftypefun void ui_out_table_end (struct ui_out *@var{uiout}) +This function signals the end of a table's output. It should be +called after the table body has been produced by the list and field +output functions. + +There should be exactly one call to @code{ui_out_table_end} for each +call to @code{ui_out_table_begin}, otherwise the @code{ui_out} +functions will signal an internal error. +@end deftypefun + +The output of the lists that represent the table rows must follow the +call to @code{ui_out_table_body} and precede the call to +@code{ui_out_table_end}. You produce the lists by calling +@code{ui_out_list_begin} and @code{ui_out_list_end}, with suitable +calls to functions which actually output fields between them. + +@deftypefun void ui_out_list_begin (struct ui_out *@var{uiout}, char *@var{lstid}) +This function marks the beginning or a list output. @var{lstid} +points to an optional string that identifies the list; it is copied by +the implementation, and so strings in @code{malloc}ed storage can be +freed after the call. +@end deftypefun + +@deftypefun void ui_out_list_end (struct ui_out *@var{uiout}) +This function signals an end of a list output. There should be +exactly one call to @code{ui_out_list_end} for each call to +@code{ui_out_list_begin}, otherwise an internal @value{GDBN} error +will be signaled. +@end deftypefun + +@subsection Item Output Functions + +@cindex item output functions +@cindex field output functions +@cindex data output +The functions described below produce output for the actual data +items, or fields, which contain information about the object. + +Choose the appropriate function accordingly to your particular needs. + +@deftypefun void ui_out_field_fmt (struct ui_out *@var{uiout}, char *@var{fldname}, char *@var{format}, ...) +This is the most general output function. It produces the +representation of the data in the variable-length argument list +according to formatting specifications in @var{format}, a +@code{printf}-like format string. The optional argument @var{fldname} +supplies the name of the field. The data items themselves are +supplied as additional arguments after @var{format}. + +This generic function should be used only when it is not possible to +use one of the specialized versions (see below). +@end deftypefun + +@deftypefun void ui_out_field_int (struct ui_out *@var{uiout}, char *@var{fldname}, int @var{value}) +This function outputs a value of an @code{int} variable. It uses the +@code{"%d"} output conversion specification. @var{fldname} specifies +the name of the field. +@end deftypefun + +@deftypefun void ui_out_field_core_addr (struct ui_out *@var{uiout}, char *@var{fldname}, CORE_ADDR @var{address}) +This function outputs an address. +@end deftypefun + +@deftypefun void ui_out_field_string (struct ui_out *@var{uiout}, char *@var{fldname}, const char *@var{string}) +This function outputs a string using the @code{"%s"} conversion +specification. +@end deftypefun + +Sometimes, there's a need to compose your output piece by piece using +functions that operate on a stream, such as @code{value_print} or +@code{fprintf_symbol_filtered}. These functions accept an argument of +the type @code{struct ui_file *}, a pointer to a @code{ui_file} object +used to store the data stream used for the output. When you use one +of these functions, you need a way to pass their results stored in a +@code{ui_file} object to the @code{ui_out} functions. To this end, +you first create a @code{ui_stream} object by calling +@code{ui_out_stream_new}, pass the @code{stream} member of that +@code{ui_stream} object to @code{value_print} and similar functions, +and finally call @code{ui_out_field_stream} to output the field you +constructed. When the @code{ui_stream} object is no longer needed, +you should destroy it and free its memory by calling +@code{ui_out_stream_delete}. + +@deftypefun struct ui_stream *ui_out_stream_new (struct ui_out *@var{uiout}) +This function creates a new @code{ui_stream} object which uses the +same output methods as the @code{ui_out} object whose pointer is +passed in @var{uiout}. It returns a pointer to the newly created +@code{ui_stream} object. +@end deftypefun + +@deftypefun void ui_out_stream_delete (struct ui_stream *@var{streambuf}) +This functions destroys a @code{ui_stream} object specified by +@var{streambuf}. +@end deftypefun + +@deftypefun void ui_out_field_stream (struct ui_out *@var{uiout}, char *@var{fieldname}, struct ui_stream *@var{streambuf}) +This function consumes all the data accumulated in +@code{streambuf->stream} and outputs it like +@code{ui_out_field_string} does. After a call to +@code{ui_out_field_stream}, the accumulated data no longer exists, but +the stream is still valid and may be used for producing more fields. +@end deftypefun + +@strong{Important:} If there is any chance that your code could bail +out before completing output generation and reaching the point where +@code{ui_out_stream_delete} is called, it is necessary to set up a +cleanup, to avoid leaking memory and other resources. Here's a +skeleton code to do that: + +@smallexample + struct ui_stream *mybuf = ui_out_stream_new (uiout); + struct cleanup *old = make_cleanup (ui_out_stream_delete, mybuf); + ... + do_cleanups (old); +@end smallexample + +If the function already has the old cleanup chain set (for other kinds +of cleanups), you just have to add your cleanup to it: + +@smallexample + mybuf = ui_out_stream_new (uiout); + make_cleanup (ui_out_stream_delete, mybuf); +@end smallexample + +Note that with cleanups in place, you should not call +@code{ui_out_stream_delete} directly, or you would attempt to free the +same buffer twice. + +@subsection Utility Output Functions + +@deftypefun void ui_out_field_skip (struct ui_out *@var{uiout}, char *@var{fldname}) +This function skips a field in a table. Use it if you have to leave +an empty field without disrupting the table alignment. The argument +@var{fldname} specifies a name for the (missing) filed. +@end deftypefun + +@deftypefun void ui_out_text (struct ui_out *@var{uiout}, char *@var{string}) +This function outputs the text in @var{string} in a way that makes it +easy to be read by humans. For example, the console implementation of +this method filters the text through a built-in pager, to prevent it +from scrolling off the visible portion of the screen. + +Use this function for printing relatively long chunks of text around +the actual field data: the text it produces is not aligned according +to the table's format. Use @code{ui_out_field_string} to output a +string field, and use @code{ui_out_message}, described below, to +output short messages. +@end deftypefun + +@deftypefun void ui_out_spaces (struct ui_out *@var{uiout}, int @var{nspaces}) +This function outputs @var{nspaces} spaces. It is handy to align the +text produced by @code{ui_out_text} with the rest of the table or +list. +@end deftypefun + +@deftypefun void ui_out_message (struct ui_out *@var{uiout}, int @var{verbosity}, char *@var{format}, ...) +This function produces a formatted message, provided that the current +verbosity level is at least as large as given by @var{verbosity}. The +current verbosity level is specified by the user with the @samp{set +verbositylevel} command.@footnote{As of this writing (April 2001), +setting verbosity level is not yet implemented, and is always returned +as zero. So calling @code{ui_out_message} with a @var{verbosity} +argument more than zero will cause the message to never be printed.} +@end deftypefun + +@deftypefun void ui_out_wrap_hint (struct ui_out *@var{uiout}, char *@var{indent}) +This function gives the console output filter (a paging filter) a hint +of where to break lines which are too long. Ignored for all other +output consumers. @var{indent}, if non-@code{NULL}, is the string to +be printed to indent the wrapped text on the next line; it must remain +accessible until the next call to @code{ui_out_wrap_hint}, or until an +explicit newline is produced by one of the other functions. If +@var{indent} is @code{NULL}, the wrapped text will not be indented. +@end deftypefun + +@deftypefun void ui_out_flush (struct ui_out *@var{uiout}) +This function flushes whatever output has been accumulated so far, if +the UI buffers output. +@end deftypefun + + +@subsection Examples of Use of @code{ui_out} functions + +@cindex using @code{ui_out} functions +@cindex @code{ui_out} functions, usage examples +This section gives some practical examples of using the @code{ui_out} +functions to generalize the old console-oriented code in +@value{GDBN}. The examples all come from functions defined on the +@file{breakpoints.c} file. + +This example, from the @code{breakpoint_1} function, shows how to +produce a table. + +The original code was: + +@example + 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 (); + @} +@end example + +Here's the new version: + +@example + 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 (); + @} +@end example + +This example, from the @code{print_one_breakpoint} function, shows how +to produce the actual data for the table whose structure was defined +in the above example. The original code was: + +@example + annotate_record (); + annotate_field (0); + printf_filtered ("%-3d ", b->number); + annotate_field (1); + if ((int)b->type > (sizeof(bptypes)/sizeof(bptypes[0])) + || ((int) b->type != bptypes[(int) b->type].type)) + internal_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]); +@end example + +This is the new version: + +@example + annotate_record (); + ui_out_list_begin (uiout, "bkpt"); + annotate_field (0); + ui_out_field_int (uiout, "number", b->number); + annotate_field (1); + if (((int) b->type > (sizeof (bptypes) / sizeof (bptypes[0]))) + || ((int) b->type != bptypes[(int) b->type].type)) + internal_error ("bptypes table does not describe type #%d.", + (int) b->type); + ui_out_field_string (uiout, "type", bptypes[(int)b->type].description); + annotate_field (2); + ui_out_field_string (uiout, "disp", bpdisps[(int)b->disposition]); + annotate_field (3); + ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int)b->enable]); +@end example + +This example, also from @code{print_one_breakpoint}, shows how to +produce a complicated output field using the @code{print_expression} +functions which requires a stream to be passed. It also shows how to +automate stream destruction with cleanups. The original code was: + +@example + annotate_field (5); + print_expression (b->exp, gdb_stdout); +@end example + +The new version is: + +@example + struct ui_stream *stb = ui_out_stream_new (uiout); + struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb); + ... + annotate_field (5); + print_expression (b->exp, stb->stream); + ui_out_field_stream (uiout, "what", local_stream); +@end example + +This example, also from @code{print_one_breakpoint}, shows how to use +@code{ui_out_text} and @code{ui_out_field_string}. The original code +was: + +@example + annotate_field (5); + if (b->dll_pathname == NULL) + printf_filtered ("<any library> "); + else + printf_filtered ("library \"%s\" ", b->dll_pathname); +@end example + +It became: + +@example + annotate_field (5); + if (b->dll_pathname == NULL) + @{ + ui_out_field_string (uiout, "what", "<any library>"); + ui_out_spaces (uiout, 1); + @} + else + @{ + ui_out_text (uiout, "library \""); + ui_out_field_string (uiout, "what", b->dll_pathname); + ui_out_text (uiout, "\" "); + @} +@end example + +The following example from @code{print_one_breakpoint} shows how to +use @code{ui_out_field_int} and @code{ui_out_spaces}. The original +code was: + +@example + annotate_field (5); + if (b->forked_inferior_pid != 0) + printf_filtered ("process %d ", b->forked_inferior_pid); +@end example + +It became: + +@example + annotate_field (5); + if (b->forked_inferior_pid != 0) + @{ + ui_out_text (uiout, "process "); + ui_out_field_int (uiout, "what", b->forked_inferior_pid); + ui_out_spaces (uiout, 1); + @} +@end example + +Here's an example of using @code{ui_out_field_string}. The original +code was: + +@example + annotate_field (5); + if (b->exec_pathname != NULL) + printf_filtered ("program \"%s\" ", b->exec_pathname); +@end example + +It became: + +@example + annotate_field (5); + if (b->exec_pathname != NULL) + @{ + ui_out_text (uiout, "program \""); + ui_out_field_string (uiout, "what", b->exec_pathname); + ui_out_text (uiout, "\" "); + @} +@end example + +Finally, here's an example of printing an address. The original code: + +@example + annotate_field (4); + printf_filtered ("%s ", + local_hex_string_custom ((unsigned long) b->address, "08l")); +@end example + +It became: + +@example + annotate_field (4); + ui_out_field_core_addr (uiout, "Address", b->address); +@end example + + @section Console Printing @section TUI