gdb/ui-out.c - gdb

Global variables defined

Data types defined

Functions defined

Source code

  1. /* Output generating routines for GDB.

  2.    Copyright (C) 1999-2015 Free Software Foundation, Inc.

  3.    Contributed by Cygnus Solutions.
  4.    Written by Fernando Nasser for Cygnus.

  5.    This file is part of GDB.

  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 3 of the License, or
  9.    (at your option) any later version.

  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.

  14.    You should have received a copy of the GNU General Public License
  15.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  16. #include "defs.h"
  17. #include "expression.h"                /* For language.h */
  18. #include "language.h"
  19. #include "ui-out.h"

  20. /* table header structures */

  21. struct ui_out_hdr
  22.   {
  23.     int colno;
  24.     int width;
  25.     int alignment;
  26.     char *col_name;
  27.     char *colhdr;
  28.     struct ui_out_hdr *next;
  29.   };

  30. /* Maintain a stack so that the info applicable to the inner most list
  31.    is always available.  Stack/nested level 0 is reserved for the
  32.    top-level result.  */

  33. enum { MAX_UI_OUT_LEVELS = 8 };

  34. struct ui_out_level
  35.   {
  36.     /* Count each field; the first element is for non-list fields.  */
  37.     int field_count;
  38.     /* The type of this level.  */
  39.     enum ui_out_type type;
  40.   };

  41. /* Define uiout->level vector types and operations.  */
  42. typedef struct ui_out_level *ui_out_level_p;
  43. DEF_VEC_P (ui_out_level_p);

  44. /* Tables are special.  Maintain a separate structure that tracks
  45.    their state.  At present an output can only contain a single table
  46.    but that restriction might eventually be lifted.  */

  47. struct ui_out_table
  48. {
  49.   /* If on, a table is being generated.  */
  50.   int flag;

  51.   /* If on, the body of a table is being generated.  If off, the table
  52.      header is being generated.  */
  53.   int body_flag;

  54.   /* The level at which each entry of the table is to be found.  A row
  55.      (a tuple) is made up of entries.  Consequently ENTRY_LEVEL is one
  56.      above that of the table.  */
  57.   int entry_level;

  58.   /* Number of table columns (as specified in the table_begin call).  */
  59.   int columns;

  60.   /* String identifying the table (as specified in the table_begin
  61.      call).  */
  62.   char *id;

  63.   /* Points to the first table header (if any).  */
  64.   struct ui_out_hdr *header_first;

  65.   /* Points to the last table header (if any).  */
  66.   struct ui_out_hdr *header_last;

  67.   /* Points to header of NEXT column to format.  */
  68.   struct ui_out_hdr *header_next;

  69. };


  70. /* The ui_out structure */
  71. /* Any change here requires a corresponding one in the initialization
  72.    of the default uiout, which is statically initialized.  */

  73. struct ui_out
  74.   {
  75.     int flags;
  76.     /* Specific implementation of ui-out.  */
  77.     const struct ui_out_impl *impl;
  78.     void *data;

  79.     /* Current level.  */
  80.     int level;

  81.     /* Vector to store and track the ui-out levels.  */
  82.     VEC (ui_out_level_p) *levels;

  83.     /* A table, if any.  At present only a single table is supported.  */
  84.     struct ui_out_table table;
  85.   };

  86. /* The current (inner most) level.  */
  87. static struct ui_out_level *
  88. current_level (struct ui_out *uiout)
  89. {
  90.   return VEC_index (ui_out_level_p, uiout->levels, uiout->level);
  91. }

  92. /* Create a new level, of TYPE.  Return the new level's index.  */
  93. static int
  94. push_level (struct ui_out *uiout,
  95.             enum ui_out_type type,
  96.             const char *id)
  97. {
  98.   struct ui_out_level *current;

  99.   uiout->level++;
  100.   current = XNEW (struct ui_out_level);
  101.   current->field_count = 0;
  102.   current->type = type;
  103.   VEC_safe_push (ui_out_level_p, uiout->levels, current);
  104.   return uiout->level;
  105. }

  106. /* Discard the current level, return the discarded level's index.
  107.    TYPE is the type of the level being discarded.  */
  108. static int
  109. pop_level (struct ui_out *uiout,
  110.            enum ui_out_type type)
  111. {
  112.   struct ui_out_level *current;

  113.   /* We had better not underflow the buffer.  */
  114.   gdb_assert (uiout->level > 0);
  115.   gdb_assert (current_level (uiout)->type == type);
  116.   current = VEC_pop (ui_out_level_p, uiout->levels);
  117.   xfree (current);
  118.   uiout->level--;
  119.   return uiout->level + 1;
  120. }


  121. /* These are the default implementation functions.  */

  122. static void default_table_begin (struct ui_out *uiout, int nbrofcols,
  123.                                  int nr_rows, const char *tblid);
  124. static void default_table_body (struct ui_out *uiout);
  125. static void default_table_end (struct ui_out *uiout);
  126. static void default_table_header (struct ui_out *uiout, int width,
  127.                                   enum ui_align alig, const char *col_name,
  128.                                   const char *colhdr);
  129. static void default_begin (struct ui_out *uiout,
  130.                            enum ui_out_type type,
  131.                            int level, const char *id);
  132. static void default_end (struct ui_out *uiout,
  133.                          enum ui_out_type type,
  134.                          int level);
  135. static void default_field_int (struct ui_out *uiout, int fldno, int width,
  136.                                enum ui_align alig,
  137.                                const char *fldname,
  138.                                int value);
  139. static void default_field_skip (struct ui_out *uiout, int fldno, int width,
  140.                                 enum ui_align alig,
  141.                                 const char *fldname);
  142. static void default_field_string (struct ui_out *uiout, int fldno, int width,
  143.                                   enum ui_align align,
  144.                                   const char *fldname,
  145.                                   const char *string);
  146. static void default_field_fmt (struct ui_out *uiout, int fldno,
  147.                                int width, enum ui_align align,
  148.                                const char *fldname,
  149.                                const char *format,
  150.                                va_list args) ATTRIBUTE_PRINTF (6, 0);
  151. static void default_spaces (struct ui_out *uiout, int numspaces);
  152. static void default_text (struct ui_out *uiout, const char *string);
  153. static void default_message (struct ui_out *uiout, int verbosity,
  154.                              const char *format,
  155.                              va_list args) ATTRIBUTE_PRINTF (3, 0);
  156. static void default_wrap_hint (struct ui_out *uiout, char *identstring);
  157. static void default_flush (struct ui_out *uiout);
  158. static void default_data_destroy (struct ui_out *uiout);

  159. /* This is the default ui-out implementation functions vector.  */

  160. const struct ui_out_impl default_ui_out_impl =
  161. {
  162.   default_table_begin,
  163.   default_table_body,
  164.   default_table_end,
  165.   default_table_header,
  166.   default_begin,
  167.   default_end,
  168.   default_field_int,
  169.   default_field_skip,
  170.   default_field_string,
  171.   default_field_fmt,
  172.   default_spaces,
  173.   default_text,
  174.   default_message,
  175.   default_wrap_hint,
  176.   default_flush,
  177.   NULL,
  178.   default_data_destroy,
  179.   0, /* Does not need MI hacks.  */
  180. };

  181. /* The default ui_out */

  182. struct ui_out def_uiout =
  183. {
  184.   0,                                /* flags */
  185.   &default_ui_out_impl,                /* impl */
  186. };

  187. /* Pointer to current ui_out */
  188. /* FIXME: This should not be a global, but something passed down from main.c
  189.    or top.c.  */

  190. struct ui_out *current_uiout = &def_uiout;

  191. /* These are the interfaces to implementation functions.  */

  192. static void uo_table_begin (struct ui_out *uiout, int nbrofcols,
  193.                             int nr_rows, const char *tblid);
  194. static void uo_table_body (struct ui_out *uiout);
  195. static void uo_table_end (struct ui_out *uiout);
  196. static void uo_table_header (struct ui_out *uiout, int width,
  197.                              enum ui_align align, const char *col_name,
  198.                              const char *colhdr);
  199. static void uo_begin (struct ui_out *uiout,
  200.                       enum ui_out_type type,
  201.                       int level, const char *id);
  202. static void uo_end (struct ui_out *uiout,
  203.                     enum ui_out_type type,
  204.                     int level);
  205. static void uo_field_int (struct ui_out *uiout, int fldno, int width,
  206.                           enum ui_align align, const char *fldname, int value);
  207. static void uo_field_skip (struct ui_out *uiout, int fldno, int width,
  208.                            enum ui_align align, const char *fldname);
  209. static void uo_field_fmt (struct ui_out *uiout, int fldno, int width,
  210.                           enum ui_align align, const char *fldname,
  211.                           const char *format, va_list args)
  212.      ATTRIBUTE_PRINTF (6, 0);
  213. static void uo_spaces (struct ui_out *uiout, int numspaces);
  214. static void uo_text (struct ui_out *uiout, const char *string);
  215. static void uo_message (struct ui_out *uiout, int verbosity,
  216.                         const char *format, va_list args)
  217.      ATTRIBUTE_PRINTF (3, 0);
  218. static void uo_wrap_hint (struct ui_out *uiout, char *identstring);
  219. static void uo_flush (struct ui_out *uiout);
  220. static int uo_redirect (struct ui_out *uiout, struct ui_file *outstream);
  221. static void uo_data_destroy (struct ui_out *uiout);

  222. /* Prototypes for local functions */

  223. extern void _initialize_ui_out (void);
  224. static void append_header_to_list (struct ui_out *uiout, int width,
  225.                                    int alignment, const char *col_name,
  226.                                    const char *colhdr);
  227. static int get_next_header (struct ui_out *uiout, int *colno, int *width,
  228.                             int *alignment, char **colhdr);
  229. static void clear_header_list (struct ui_out *uiout);
  230. static void clear_table (struct ui_out *uiout);
  231. static void verify_field (struct ui_out *uiout, int *fldno, int *width,
  232.                           int *align);

  233. /* exported functions (ui_out API) */

  234. /* Mark beginning of a table.  */

  235. static void
  236. ui_out_table_begin (struct ui_out *uiout, int nbrofcols,
  237.                     int nr_rows,
  238.                     const char *tblid)
  239. {
  240.   if (uiout->table.flag)
  241.     internal_error (__FILE__, __LINE__,
  242.                     _("tables cannot be nested; table_begin found before \
  243. previous table_end."));

  244.   uiout->table.flag = 1;
  245.   uiout->table.body_flag = 0;
  246.   uiout->table.entry_level = uiout->level + 1;
  247.   uiout->table.columns = nbrofcols;
  248.   if (tblid != NULL)
  249.     uiout->table.id = xstrdup (tblid);
  250.   else
  251.     uiout->table.id = NULL;
  252.   clear_header_list (uiout);

  253.   uo_table_begin (uiout, nbrofcols, nr_rows, uiout->table.id);
  254. }

  255. void
  256. ui_out_table_body (struct ui_out *uiout)
  257. {
  258.   if (!uiout->table.flag)
  259.     internal_error (__FILE__, __LINE__,
  260.                     _("table_body outside a table is not valid; it must be \
  261. after a table_begin and before a table_end."));
  262.   if (uiout->table.body_flag)
  263.     internal_error (__FILE__, __LINE__,
  264.                     _("extra table_body call not allowed; there must be \
  265. only one table_body after a table_begin and before a table_end."));
  266.   if (uiout->table.header_next->colno != uiout->table.columns)
  267.     internal_error (__FILE__, __LINE__,
  268.                     _("number of headers differ from number of table \
  269. columns."));

  270.   uiout->table.body_flag = 1;
  271.   uiout->table.header_next = uiout->table.header_first;

  272.   uo_table_body (uiout);
  273. }

  274. static void
  275. ui_out_table_end (struct ui_out *uiout)
  276. {
  277.   if (!uiout->table.flag)
  278.     internal_error (__FILE__, __LINE__,
  279.                     _("misplaced table_end or missing table_begin."));

  280.   uiout->table.entry_level = 0;
  281.   uiout->table.body_flag = 0;
  282.   uiout->table.flag = 0;

  283.   uo_table_end (uiout);
  284.   clear_table (uiout);
  285. }

  286. void
  287. ui_out_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
  288.                      const char *col_name,
  289.                      const char *colhdr)
  290. {
  291.   if (!uiout->table.flag || uiout->table.body_flag)
  292.     internal_error (__FILE__, __LINE__,
  293.                     _("table header must be specified after table_begin \
  294. and before table_body."));

  295.   append_header_to_list (uiout, width, alignment, col_name, colhdr);

  296.   uo_table_header (uiout, width, alignment, col_name, colhdr);
  297. }

  298. static void
  299. do_cleanup_table_end (void *data)
  300. {
  301.   struct ui_out *ui_out = data;

  302.   ui_out_table_end (ui_out);
  303. }

  304. struct cleanup *
  305. make_cleanup_ui_out_table_begin_end (struct ui_out *ui_out, int nr_cols,
  306.                                      int nr_rows, const char *tblid)
  307. {
  308.   ui_out_table_begin (ui_out, nr_cols, nr_rows, tblid);
  309.   return make_cleanup (do_cleanup_table_end, ui_out);
  310. }

  311. void
  312. ui_out_begin (struct ui_out *uiout,
  313.               enum ui_out_type type,
  314.               const char *id)
  315. {
  316.   int new_level;

  317.   if (uiout->table.flag && !uiout->table.body_flag)
  318.     internal_error (__FILE__, __LINE__,
  319.                     _("table header or table_body expected; lists must be \
  320. specified after table_body."));

  321.   /* Be careful to verify the ``field'' before the new tuple/list is
  322.      pushed onto the stack.  That way the containing list/table/row is
  323.      verified and not the newly created tuple/list.  This verification
  324.      is needed (at least) for the case where a table row entry
  325.      contains either a tuple/list.  For that case bookkeeping such as
  326.      updating the column count or advancing to the next heading still
  327.      needs to be performed.  */
  328.   {
  329.     int fldno;
  330.     int width;
  331.     int align;

  332.     verify_field (uiout, &fldno, &width, &align);
  333.   }

  334.   new_level = push_level (uiout, type, id);

  335.   /* If the push puts us at the same level as a table row entry, we've
  336.      got a new table row.  Put the header pointer back to the start.  */
  337.   if (uiout->table.body_flag
  338.       && uiout->table.entry_level == new_level)
  339.     uiout->table.header_next = uiout->table.header_first;

  340.   uo_begin (uiout, type, new_level, id);
  341. }

  342. void
  343. ui_out_end (struct ui_out *uiout,
  344.             enum ui_out_type type)
  345. {
  346.   int old_level = pop_level (uiout, type);

  347.   uo_end (uiout, type, old_level);
  348. }

  349. struct ui_out_end_cleanup_data
  350. {
  351.   struct ui_out *uiout;
  352.   enum ui_out_type type;
  353. };

  354. static void
  355. do_cleanup_end (void *data)
  356. {
  357.   struct ui_out_end_cleanup_data *end_cleanup_data = data;

  358.   ui_out_end (end_cleanup_data->uiout, end_cleanup_data->type);
  359.   xfree (end_cleanup_data);
  360. }

  361. static struct cleanup *
  362. make_cleanup_ui_out_end (struct ui_out *uiout,
  363.                          enum ui_out_type type)
  364. {
  365.   struct ui_out_end_cleanup_data *end_cleanup_data;

  366.   end_cleanup_data = XNEW (struct ui_out_end_cleanup_data);
  367.   end_cleanup_data->uiout = uiout;
  368.   end_cleanup_data->type = type;
  369.   return make_cleanup (do_cleanup_end, end_cleanup_data);
  370. }

  371. struct cleanup *
  372. make_cleanup_ui_out_tuple_begin_end (struct ui_out *uiout,
  373.                                      const char *id)
  374. {
  375.   ui_out_begin (uiout, ui_out_type_tuple, id);
  376.   return make_cleanup_ui_out_end (uiout, ui_out_type_tuple);
  377. }

  378. struct cleanup *
  379. make_cleanup_ui_out_list_begin_end (struct ui_out *uiout,
  380.                                     const char *id)
  381. {
  382.   ui_out_begin (uiout, ui_out_type_list, id);
  383.   return make_cleanup_ui_out_end (uiout, ui_out_type_list);
  384. }

  385. void
  386. ui_out_field_int (struct ui_out *uiout,
  387.                   const char *fldname,
  388.                   int value)
  389. {
  390.   int fldno;
  391.   int width;
  392.   int align;

  393.   verify_field (uiout, &fldno, &width, &align);

  394.   uo_field_int (uiout, fldno, width, align, fldname, value);
  395. }

  396. void
  397. ui_out_field_fmt_int (struct ui_out *uiout,
  398.                       int input_width,
  399.                       enum ui_align input_align,
  400.                       const char *fldname,
  401.                       int value)
  402. {
  403.   int fldno;
  404.   int width;
  405.   int align;

  406.   verify_field (uiout, &fldno, &width, &align);

  407.   uo_field_int (uiout, fldno, input_width, input_align, fldname, value);
  408. }

  409. /* Documented in ui-out.h.  */

  410. void
  411. ui_out_field_core_addr (struct ui_out *uiout,
  412.                         const char *fldname,
  413.                         struct gdbarch *gdbarch,
  414.                         CORE_ADDR address)
  415. {
  416.   ui_out_field_string (uiout, fldname,
  417.                        print_core_address (gdbarch, address));
  418. }

  419. void
  420. ui_out_field_stream (struct ui_out *uiout,
  421.                      const char *fldname,
  422.                      struct ui_file *stream)
  423. {
  424.   long length;
  425.   char *buffer = ui_file_xstrdup (stream, &length);
  426.   struct cleanup *old_cleanup = make_cleanup (xfree, buffer);

  427.   if (length > 0)
  428.     ui_out_field_string (uiout, fldname, buffer);
  429.   else
  430.     ui_out_field_skip (uiout, fldname);
  431.   ui_file_rewind (stream);
  432.   do_cleanups (old_cleanup);
  433. }

  434. /* Used to omit a field.  */

  435. void
  436. ui_out_field_skip (struct ui_out *uiout,
  437.                    const char *fldname)
  438. {
  439.   int fldno;
  440.   int width;
  441.   int align;

  442.   verify_field (uiout, &fldno, &width, &align);

  443.   uo_field_skip (uiout, fldno, width, align, fldname);
  444. }

  445. void
  446. ui_out_field_string (struct ui_out *uiout,
  447.                      const char *fldname,
  448.                      const char *string)
  449. {
  450.   int fldno;
  451.   int width;
  452.   int align;

  453.   verify_field (uiout, &fldno, &width, &align);

  454.   uo_field_string (uiout, fldno, width, align, fldname, string);
  455. }

  456. /* VARARGS */
  457. void
  458. ui_out_field_fmt (struct ui_out *uiout,
  459.                   const char *fldname,
  460.                   const char *format, ...)
  461. {
  462.   va_list args;
  463.   int fldno;
  464.   int width;
  465.   int align;

  466.   /* Will not align, but has to call anyway.  */
  467.   verify_field (uiout, &fldno, &width, &align);

  468.   va_start (args, format);

  469.   uo_field_fmt (uiout, fldno, width, align, fldname, format, args);

  470.   va_end (args);
  471. }

  472. void
  473. ui_out_spaces (struct ui_out *uiout, int numspaces)
  474. {
  475.   uo_spaces (uiout, numspaces);
  476. }

  477. void
  478. ui_out_text (struct ui_out *uiout,
  479.              const char *string)
  480. {
  481.   uo_text (uiout, string);
  482. }

  483. void
  484. ui_out_message (struct ui_out *uiout, int verbosity,
  485.                 const char *format,...)
  486. {
  487.   va_list args;

  488.   va_start (args, format);
  489.   uo_message (uiout, verbosity, format, args);
  490.   va_end (args);
  491. }

  492. void
  493. ui_out_wrap_hint (struct ui_out *uiout, char *identstring)
  494. {
  495.   uo_wrap_hint (uiout, identstring);
  496. }

  497. void
  498. ui_out_flush (struct ui_out *uiout)
  499. {
  500.   uo_flush (uiout);
  501. }

  502. int
  503. ui_out_redirect (struct ui_out *uiout, struct ui_file *outstream)
  504. {
  505.   return uo_redirect (uiout, outstream);
  506. }

  507. /* Set the flags specified by the mask given.  */
  508. int
  509. ui_out_set_flags (struct ui_out *uiout, int mask)
  510. {
  511.   int oldflags = uiout->flags;

  512.   uiout->flags |= mask;
  513.   return oldflags;
  514. }

  515. /* Clear the flags specified by the mask given.  */
  516. int
  517. ui_out_clear_flags (struct ui_out *uiout, int mask)
  518. {
  519.   int oldflags = uiout->flags;

  520.   uiout->flags &= ~mask;
  521.   return oldflags;
  522. }

  523. /* Test the flags against the mask given.  */
  524. int
  525. ui_out_test_flags (struct ui_out *uiout, int mask)
  526. {
  527.   return (uiout->flags & mask);
  528. }

  529. /* Obtain the current verbosity level (as stablished by the
  530.    'set verbositylevel' command.  */

  531. int
  532. ui_out_get_verblvl (struct ui_out *uiout)
  533. {
  534.   /* FIXME: not implemented yet.  */
  535.   return 0;
  536. }

  537. int
  538. ui_out_is_mi_like_p (struct ui_out *uiout)
  539. {
  540.   return uiout->impl->is_mi_like_p;
  541. }

  542. /* Default gdb-out hook functions.  */

  543. static void
  544. default_table_begin (struct ui_out *uiout, int nbrofcols,
  545.                      int nr_rows,
  546.                      const char *tblid)
  547. {
  548. }

  549. static void
  550. default_table_body (struct ui_out *uiout)
  551. {
  552. }

  553. static void
  554. default_table_end (struct ui_out *uiout)
  555. {
  556. }

  557. static void
  558. default_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
  559.                       const char *col_name,
  560.                       const char *colhdr)
  561. {
  562. }

  563. static void
  564. default_begin (struct ui_out *uiout,
  565.                enum ui_out_type type,
  566.                int level,
  567.                const char *id)
  568. {
  569. }

  570. static void
  571. default_end (struct ui_out *uiout,
  572.              enum ui_out_type type,
  573.              int level)
  574. {
  575. }

  576. static void
  577. default_field_int (struct ui_out *uiout, int fldno, int width,
  578.                    enum ui_align align,
  579.                    const char *fldname, int value)
  580. {
  581. }

  582. static void
  583. default_field_skip (struct ui_out *uiout, int fldno, int width,
  584.                     enum ui_align align, const char *fldname)
  585. {
  586. }

  587. static void
  588. default_field_string (struct ui_out *uiout,
  589.                       int fldno,
  590.                       int width,
  591.                       enum ui_align align,
  592.                       const char *fldname,
  593.                       const char *string)
  594. {
  595. }

  596. static void
  597. default_field_fmt (struct ui_out *uiout, int fldno, int width,
  598.                    enum ui_align align,
  599.                    const char *fldname,
  600.                    const char *format,
  601.                    va_list args)
  602. {
  603. }

  604. static void
  605. default_spaces (struct ui_out *uiout, int numspaces)
  606. {
  607. }

  608. static void
  609. default_text (struct ui_out *uiout, const char *string)
  610. {
  611. }

  612. static void
  613. default_message (struct ui_out *uiout, int verbosity,
  614.                  const char *format,
  615.                  va_list args)
  616. {
  617. }

  618. static void
  619. default_wrap_hint (struct ui_out *uiout, char *identstring)
  620. {
  621. }

  622. static void
  623. default_flush (struct ui_out *uiout)
  624. {
  625. }

  626. static void
  627. default_data_destroy (struct ui_out *uiout)
  628. {
  629. }

  630. /* Interface to the implementation functions.  */

  631. void
  632. uo_table_begin (struct ui_out *uiout, int nbrofcols,
  633.                 int nr_rows,
  634.                 const char *tblid)
  635. {
  636.   if (!uiout->impl->table_begin)
  637.     return;
  638.   uiout->impl->table_begin (uiout, nbrofcols, nr_rows, tblid);
  639. }

  640. void
  641. uo_table_body (struct ui_out *uiout)
  642. {
  643.   if (!uiout->impl->table_body)
  644.     return;
  645.   uiout->impl->table_body (uiout);
  646. }

  647. void
  648. uo_table_end (struct ui_out *uiout)
  649. {
  650.   if (!uiout->impl->table_end)
  651.     return;
  652.   uiout->impl->table_end (uiout);
  653. }

  654. void
  655. uo_table_header (struct ui_out *uiout, int width, enum ui_align align,
  656.                  const char *col_name,
  657.                  const char *colhdr)
  658. {
  659.   if (!uiout->impl->table_header)
  660.     return;
  661.   uiout->impl->table_header (uiout, width, align, col_name, colhdr);
  662. }

  663. /* Clear the table associated with UIOUT.  */

  664. static void
  665. clear_table (struct ui_out *uiout)
  666. {
  667.   xfree (uiout->table.id);
  668.   uiout->table.id = NULL;
  669.   clear_header_list (uiout);
  670. }

  671. void
  672. uo_begin (struct ui_out *uiout,
  673.           enum ui_out_type type,
  674.           int level,
  675.           const char *id)
  676. {
  677.   if (uiout->impl->begin == NULL)
  678.     return;
  679.   uiout->impl->begin (uiout, type, level, id);
  680. }

  681. void
  682. uo_end (struct ui_out *uiout,
  683.         enum ui_out_type type,
  684.         int level)
  685. {
  686.   if (uiout->impl->end == NULL)
  687.     return;
  688.   uiout->impl->end (uiout, type, level);
  689. }

  690. void
  691. uo_field_int (struct ui_out *uiout, int fldno, int width, enum ui_align align,
  692.               const char *fldname,
  693.               int value)
  694. {
  695.   if (!uiout->impl->field_int)
  696.     return;
  697.   uiout->impl->field_int (uiout, fldno, width, align, fldname, value);
  698. }

  699. void
  700. uo_field_skip (struct ui_out *uiout, int fldno, int width, enum ui_align align,
  701.                const char *fldname)
  702. {
  703.   if (!uiout->impl->field_skip)
  704.     return;
  705.   uiout->impl->field_skip (uiout, fldno, width, align, fldname);
  706. }

  707. void
  708. uo_field_string (struct ui_out *uiout, int fldno, int width,
  709.                  enum ui_align align,
  710.                  const char *fldname,
  711.                  const char *string)
  712. {
  713.   if (!uiout->impl->field_string)
  714.     return;
  715.   uiout->impl->field_string (uiout, fldno, width, align, fldname, string);
  716. }

  717. void
  718. uo_field_fmt (struct ui_out *uiout, int fldno, int width, enum ui_align align,
  719.               const char *fldname,
  720.               const char *format,
  721.               va_list args)
  722. {
  723.   if (!uiout->impl->field_fmt)
  724.     return;
  725.   uiout->impl->field_fmt (uiout, fldno, width, align, fldname, format, args);
  726. }

  727. void
  728. uo_spaces (struct ui_out *uiout, int numspaces)
  729. {
  730.   if (!uiout->impl->spaces)
  731.     return;
  732.   uiout->impl->spaces (uiout, numspaces);
  733. }

  734. void
  735. uo_text (struct ui_out *uiout,
  736.          const char *string)
  737. {
  738.   if (!uiout->impl->text)
  739.     return;
  740.   uiout->impl->text (uiout, string);
  741. }

  742. void
  743. uo_message (struct ui_out *uiout, int verbosity,
  744.             const char *format,
  745.             va_list args)
  746. {
  747.   if (!uiout->impl->message)
  748.     return;
  749.   uiout->impl->message (uiout, verbosity, format, args);
  750. }

  751. void
  752. uo_wrap_hint (struct ui_out *uiout, char *identstring)
  753. {
  754.   if (!uiout->impl->wrap_hint)
  755.     return;
  756.   uiout->impl->wrap_hint (uiout, identstring);
  757. }

  758. void
  759. uo_flush (struct ui_out *uiout)
  760. {
  761.   if (!uiout->impl->flush)
  762.     return;
  763.   uiout->impl->flush (uiout);
  764. }

  765. int
  766. uo_redirect (struct ui_out *uiout, struct ui_file *outstream)
  767. {
  768.   if (!uiout->impl->redirect)
  769.     return -1;
  770.   uiout->impl->redirect (uiout, outstream);
  771.   return 0;
  772. }

  773. void
  774. uo_data_destroy (struct ui_out *uiout)
  775. {
  776.   if (!uiout->impl->data_destroy)
  777.     return;

  778.   uiout->impl->data_destroy (uiout);
  779. }

  780. /* local functions */

  781. /* List of column headers manipulation routines.  */

  782. static void
  783. clear_header_list (struct ui_out *uiout)
  784. {
  785.   while (uiout->table.header_first != NULL)
  786.     {
  787.       uiout->table.header_next = uiout->table.header_first;
  788.       uiout->table.header_first = uiout->table.header_first->next;
  789.       xfree (uiout->table.header_next->colhdr);
  790.       xfree (uiout->table.header_next->col_name);
  791.       xfree (uiout->table.header_next);
  792.     }
  793.   gdb_assert (uiout->table.header_first == NULL);
  794.   uiout->table.header_last = NULL;
  795.   uiout->table.header_next = NULL;
  796. }

  797. static void
  798. append_header_to_list (struct ui_out *uiout,
  799.                        int width,
  800.                        int alignment,
  801.                        const char *col_name,
  802.                        const char *colhdr)
  803. {
  804.   struct ui_out_hdr *temphdr;

  805.   temphdr = XNEW (struct ui_out_hdr);
  806.   temphdr->width = width;
  807.   temphdr->alignment = alignment;
  808.   /* We have to copy the column title as the original may be an
  809.      automatic.  */
  810.   if (colhdr != NULL)
  811.     temphdr->colhdr = xstrdup (colhdr);
  812.   else
  813.     temphdr->colhdr = NULL;

  814.   if (col_name != NULL)
  815.     temphdr->col_name = xstrdup (col_name);
  816.   else if (colhdr != NULL)
  817.     temphdr->col_name = xstrdup (colhdr);
  818.   else
  819.     temphdr->col_name = NULL;

  820.   temphdr->next = NULL;
  821.   if (uiout->table.header_first == NULL)
  822.     {
  823.       temphdr->colno = 1;
  824.       uiout->table.header_first = temphdr;
  825.       uiout->table.header_last = temphdr;
  826.     }
  827.   else
  828.     {
  829.       temphdr->colno = uiout->table.header_last->colno + 1;
  830.       uiout->table.header_last->next = temphdr;
  831.       uiout->table.header_last = temphdr;
  832.     }
  833.   uiout->table.header_next = uiout->table.header_last;
  834. }

  835. /* Extract the format information for the NEXT header and advance
  836.    the header pointer.  Return 0 if there was no next header.  */

  837. static int
  838. get_next_header (struct ui_out *uiout,
  839.                  int *colno,
  840.                  int *width,
  841.                  int *alignment,
  842.                  char **colhdr)
  843. {
  844.   /* There may be no headers at all or we may have used all columns.  */
  845.   if (uiout->table.header_next == NULL)
  846.     return 0;
  847.   *colno = uiout->table.header_next->colno;
  848.   *width = uiout->table.header_next->width;
  849.   *alignment = uiout->table.header_next->alignment;
  850.   *colhdr = uiout->table.header_next->colhdr;
  851.   /* Advance the header pointer to the next entry.  */
  852.   uiout->table.header_next = uiout->table.header_next->next;
  853.   return 1;
  854. }


  855. /* Verify that the field/tuple/list is correctly positioned.  Return
  856.    the field number and corresponding alignment (if
  857.    available/applicable).  */

  858. static void
  859. verify_field (struct ui_out *uiout, int *fldno, int *width, int *align)
  860. {
  861.   struct ui_out_level *current = current_level (uiout);
  862.   char *text;

  863.   if (uiout->table.flag)
  864.     {
  865.       if (!uiout->table.body_flag)
  866.         internal_error (__FILE__, __LINE__,
  867.                         _("table_body missing; table fields must be \
  868. specified after table_body and inside a list."));
  869.       /* NOTE: cagney/2001-12-08: There was a check here to ensure
  870.          that this code was only executed when uiout->level was
  871.          greater than zero.  That no longer applies - this code is run
  872.          before each table row tuple is started and at that point the
  873.          level is zero.  */
  874.     }

  875.   current->field_count += 1;

  876.   if (uiout->table.body_flag
  877.       && uiout->table.entry_level == uiout->level
  878.       && get_next_header (uiout, fldno, width, align, &text))
  879.     {
  880.       if (*fldno != current->field_count)
  881.         internal_error (__FILE__, __LINE__,
  882.                         _("ui-out internal error in handling headers."));
  883.     }
  884.   else
  885.     {
  886.       *width = 0;
  887.       *align = ui_noalign;
  888.       *fldno = current->field_count;
  889.     }
  890. }


  891. /* Access to ui-out members data.  */

  892. void *
  893. ui_out_data (struct ui_out *uiout)
  894. {
  895.   return uiout->data;
  896. }

  897. /* Access table field parameters.  */
  898. int
  899. ui_out_query_field (struct ui_out *uiout, int colno,
  900.                     int *width, int *alignment, char **col_name)
  901. {
  902.   struct ui_out_hdr *hdr;

  903.   if (!uiout->table.flag)
  904.     return 0;

  905.   for (hdr = uiout->table.header_first; hdr; hdr = hdr->next)
  906.     if (hdr->colno == colno)
  907.       {
  908.         *width = hdr->width;
  909.         *alignment = hdr->alignment;
  910.         *col_name = hdr->col_name;
  911.         return 1;
  912.       }

  913.   return 0;
  914. }

  915. /* Initalize private members at startup.  */

  916. struct ui_out *
  917. ui_out_new (const struct ui_out_impl *impl, void *data,
  918.             int flags)
  919. {
  920.   struct ui_out *uiout = XNEW (struct ui_out);
  921.   struct ui_out_level *current = XNEW (struct ui_out_level);

  922.   uiout->data = data;
  923.   uiout->impl = impl;
  924.   uiout->flags = flags;
  925.   uiout->table.flag = 0;
  926.   uiout->table.body_flag = 0;
  927.   uiout->level = 0;
  928.   uiout->levels = NULL;

  929.   /* Create uiout->level 0, the default level.  */
  930.   current->type = ui_out_type_tuple;
  931.   current->field_count = 0;
  932.   VEC_safe_push (ui_out_level_p, uiout->levels, current);

  933.   uiout->table.id = NULL;
  934.   uiout->table.header_first = NULL;
  935.   uiout->table.header_last = NULL;
  936.   uiout->table.header_next = NULL;
  937.   return uiout;
  938. }

  939. /* Free  UIOUT and the memory areas it references.  */

  940. void
  941. ui_out_destroy (struct ui_out *uiout)
  942. {
  943.   int i;
  944.   struct ui_out_level *current;

  945.   /* Make sure that all levels are freed in the case where levels have
  946.      been pushed, but not popped before the ui_out object is
  947.      destroyed.  */
  948.   for (i = 0;
  949.        VEC_iterate (ui_out_level_p, uiout->levels, i, current);
  950.        ++i)
  951.     xfree (current);

  952.   VEC_free (ui_out_level_p, uiout->levels);
  953.   uo_data_destroy (uiout);
  954.   clear_table (uiout);
  955.   xfree (uiout);
  956. }

  957. /* Standard gdb initialization hook.  */

  958. void
  959. _initialize_ui_out (void)
  960. {
  961.   /* nothing needs to be done */
  962. }