gdb/cli-out.c - gdb

Global variables defined

Data types defined

Functions defined

Source code

  1. /* Output generating routines for GDB CLI.

  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 "ui-out.h"
  18. #include "cli-out.h"
  19. #include "vec.h"

  20. typedef struct cli_ui_out_data cli_out_data;


  21. /* Prototypes for local functions */

  22. static void cli_text (struct ui_out *uiout, const char *string);

  23. static void field_separator (void);

  24. static void out_field_fmt (struct ui_out *uiout, int fldno,
  25.                            const char *fldname,
  26.                            const char *format,...) ATTRIBUTE_PRINTF (4, 5);

  27. /* The destructor.  */

  28. static void
  29. cli_uiout_dtor (struct ui_out *ui_out)
  30. {
  31.   cli_out_data *data = ui_out_data (ui_out);

  32.   VEC_free (ui_filep, data->streams);
  33.   xfree (data);
  34. }

  35. /* These are the CLI output functions */

  36. /* Mark beginning of a table */

  37. static void
  38. cli_table_begin (struct ui_out *uiout, int nbrofcols,
  39.                  int nr_rows,
  40.                  const char *tblid)
  41. {
  42.   cli_out_data *data = ui_out_data (uiout);

  43.   if (nr_rows == 0)
  44.     data->suppress_output = 1;
  45.   else
  46.     /* Only the table suppresses the output and, fortunately, a table
  47.        is not a recursive data structure.  */
  48.     gdb_assert (data->suppress_output == 0);
  49. }

  50. /* Mark beginning of a table body */

  51. static void
  52. cli_table_body (struct ui_out *uiout)
  53. {
  54.   cli_out_data *data = ui_out_data (uiout);

  55.   if (data->suppress_output)
  56.     return;
  57.   /* first, close the table header line */
  58.   cli_text (uiout, "\n");
  59. }

  60. /* Mark end of a table */

  61. static void
  62. cli_table_end (struct ui_out *uiout)
  63. {
  64.   cli_out_data *data = ui_out_data (uiout);

  65.   data->suppress_output = 0;
  66. }

  67. /* Specify table header */

  68. static void
  69. cli_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
  70.                   const char *col_name,
  71.                   const char *colhdr)
  72. {
  73.   cli_out_data *data = ui_out_data (uiout);

  74.   if (data->suppress_output)
  75.     return;

  76.   /* Always go through the function pointer (virtual function call).
  77.      We may have been extended.  */
  78.   uo_field_string (uiout, 0, width, alignment, 0, colhdr);
  79. }

  80. /* Mark beginning of a list */

  81. static void
  82. cli_begin (struct ui_out *uiout,
  83.            enum ui_out_type type,
  84.            int level,
  85.            const char *id)
  86. {
  87.   cli_out_data *data = ui_out_data (uiout);

  88.   if (data->suppress_output)
  89.     return;
  90. }

  91. /* Mark end of a list */

  92. static void
  93. cli_end (struct ui_out *uiout,
  94.          enum ui_out_type type,
  95.          int level)
  96. {
  97.   cli_out_data *data = ui_out_data (uiout);

  98.   if (data->suppress_output)
  99.     return;
  100. }

  101. /* output an int field */

  102. static void
  103. cli_field_int (struct ui_out *uiout, int fldno, int width,
  104.                enum ui_align alignment,
  105.                const char *fldname, int value)
  106. {
  107.   char buffer[20];        /* FIXME: how many chars long a %d can become? */
  108.   cli_out_data *data = ui_out_data (uiout);

  109.   if (data->suppress_output)
  110.     return;
  111.   xsnprintf (buffer, sizeof (buffer), "%d", value);

  112.   /* Always go through the function pointer (virtual function call).
  113.      We may have been extended.  */
  114.   uo_field_string (uiout, fldno, width, alignment, fldname, buffer);
  115. }

  116. /* used to ommit a field */

  117. static void
  118. cli_field_skip (struct ui_out *uiout, int fldno, int width,
  119.                 enum ui_align alignment,
  120.                 const char *fldname)
  121. {
  122.   cli_out_data *data = ui_out_data (uiout);

  123.   if (data->suppress_output)
  124.     return;

  125.   /* Always go through the function pointer (virtual function call).
  126.      We may have been extended.  */
  127.   uo_field_string (uiout, fldno, width, alignment, fldname, "");
  128. }

  129. /* other specific cli_field_* end up here so alignment and field
  130.    separators are both handled by cli_field_string */

  131. static void
  132. cli_field_string (struct ui_out *uiout,
  133.                   int fldno,
  134.                   int width,
  135.                   enum ui_align align,
  136.                   const char *fldname,
  137.                   const char *string)
  138. {
  139.   int before = 0;
  140.   int after = 0;
  141.   cli_out_data *data = ui_out_data (uiout);

  142.   if (data->suppress_output)
  143.     return;

  144.   if ((align != ui_noalign) && string)
  145.     {
  146.       before = width - strlen (string);
  147.       if (before <= 0)
  148.         before = 0;
  149.       else
  150.         {
  151.           if (align == ui_right)
  152.             after = 0;
  153.           else if (align == ui_left)
  154.             {
  155.               after = before;
  156.               before = 0;
  157.             }
  158.           else
  159.             /* ui_center */
  160.             {
  161.               after = before / 2;
  162.               before -= after;
  163.             }
  164.         }
  165.     }

  166.   if (before)
  167.     ui_out_spaces (uiout, before);
  168.   if (string)
  169.     out_field_fmt (uiout, fldno, fldname, "%s", string);
  170.   if (after)
  171.     ui_out_spaces (uiout, after);

  172.   if (align != ui_noalign)
  173.     field_separator ();
  174. }

  175. /* This is the only field function that does not align.  */

  176. static void ATTRIBUTE_PRINTF (6, 0)
  177. cli_field_fmt (struct ui_out *uiout, int fldno,
  178.                int width, enum ui_align align,
  179.                const char *fldname,
  180.                const char *format,
  181.                va_list args)
  182. {
  183.   cli_out_data *data = ui_out_data (uiout);
  184.   struct ui_file *stream;

  185.   if (data->suppress_output)
  186.     return;

  187.   stream = VEC_last (ui_filep, data->streams);
  188.   vfprintf_filtered (stream, format, args);

  189.   if (align != ui_noalign)
  190.     field_separator ();
  191. }

  192. static void
  193. cli_spaces (struct ui_out *uiout, int numspaces)
  194. {
  195.   cli_out_data *data = ui_out_data (uiout);
  196.   struct ui_file *stream;

  197.   if (data->suppress_output)
  198.     return;

  199.   stream = VEC_last (ui_filep, data->streams);
  200.   print_spaces_filtered (numspaces, stream);
  201. }

  202. static void
  203. cli_text (struct ui_out *uiout, const char *string)
  204. {
  205.   cli_out_data *data = ui_out_data (uiout);
  206.   struct ui_file *stream;

  207.   if (data->suppress_output)
  208.     return;

  209.   stream = VEC_last (ui_filep, data->streams);
  210.   fputs_filtered (string, stream);
  211. }

  212. static void ATTRIBUTE_PRINTF (3, 0)
  213. cli_message (struct ui_out *uiout, int verbosity,
  214.              const char *format, va_list args)
  215. {
  216.   cli_out_data *data = ui_out_data (uiout);

  217.   if (data->suppress_output)
  218.     return;

  219.   if (ui_out_get_verblvl (uiout) >= verbosity)
  220.     {
  221.       struct ui_file *stream = VEC_last (ui_filep, data->streams);

  222.       vfprintf_unfiltered (stream, format, args);
  223.     }
  224. }

  225. static void
  226. cli_wrap_hint (struct ui_out *uiout, char *identstring)
  227. {
  228.   cli_out_data *data = ui_out_data (uiout);

  229.   if (data->suppress_output)
  230.     return;
  231.   wrap_here (identstring);
  232. }

  233. static void
  234. cli_flush (struct ui_out *uiout)
  235. {
  236.   cli_out_data *data = ui_out_data (uiout);
  237.   struct ui_file *stream = VEC_last (ui_filep, data->streams);

  238.   gdb_flush (stream);
  239. }

  240. /* OUTSTREAM as non-NULL will push OUTSTREAM on the stack of output streams
  241.    and make it therefore active.  OUTSTREAM as NULL will pop the last pushed
  242.    output stream; it is an internal error if it does not exist.  */

  243. static int
  244. cli_redirect (struct ui_out *uiout, struct ui_file *outstream)
  245. {
  246.   cli_out_data *data = ui_out_data (uiout);

  247.   if (outstream != NULL)
  248.     VEC_safe_push (ui_filep, data->streams, outstream);
  249.   else
  250.     VEC_pop (ui_filep, data->streams);

  251.   return 0;
  252. }

  253. /* local functions */

  254. /* Like cli_field_fmt, but takes a variable number of args
  255.    and makes a va_list and does not insert a separator.  */

  256. /* VARARGS */
  257. static void
  258. out_field_fmt (struct ui_out *uiout, int fldno,
  259.                const char *fldname,
  260.                const char *format,...)
  261. {
  262.   cli_out_data *data = ui_out_data (uiout);
  263.   struct ui_file *stream = VEC_last (ui_filep, data->streams);
  264.   va_list args;

  265.   va_start (args, format);
  266.   vfprintf_filtered (stream, format, args);

  267.   va_end (args);
  268. }

  269. /* Access to ui_out format private members.  */

  270. static void
  271. field_separator (void)
  272. {
  273.   cli_out_data *data = ui_out_data (current_uiout);
  274.   struct ui_file *stream = VEC_last (ui_filep, data->streams);

  275.   fputc_filtered (' ', stream);
  276. }

  277. /* This is the CLI ui-out implementation functions vector */

  278. const struct ui_out_impl cli_ui_out_impl =
  279. {
  280.   cli_table_begin,
  281.   cli_table_body,
  282.   cli_table_end,
  283.   cli_table_header,
  284.   cli_begin,
  285.   cli_end,
  286.   cli_field_int,
  287.   cli_field_skip,
  288.   cli_field_string,
  289.   cli_field_fmt,
  290.   cli_spaces,
  291.   cli_text,
  292.   cli_message,
  293.   cli_wrap_hint,
  294.   cli_flush,
  295.   cli_redirect,
  296.   cli_uiout_dtor,
  297.   0, /* Does not need MI hacks (i.e. needs CLI hacks).  */
  298. };

  299. /* Constructor for a `cli_out_data' object.  */

  300. void
  301. cli_out_data_ctor (cli_out_data *self, struct ui_file *stream)
  302. {
  303.   gdb_assert (stream != NULL);

  304.   self->streams = NULL;
  305.   VEC_safe_push (ui_filep, self->streams, stream);

  306.   self->suppress_output = 0;
  307. }

  308. /* Initialize private members at startup.  */

  309. struct ui_out *
  310. cli_out_new (struct ui_file *stream)
  311. {
  312.   int flags = ui_source_list;
  313.   cli_out_data *data = XNEW (cli_out_data);

  314.   cli_out_data_ctor (data, stream);
  315.   return ui_out_new (&cli_ui_out_impl, data, flags);
  316. }

  317. struct ui_file *
  318. cli_out_set_stream (struct ui_out *uiout, struct ui_file *stream)
  319. {
  320.   cli_out_data *data = ui_out_data (uiout);
  321.   struct ui_file *old;

  322.   old = VEC_pop (ui_filep, data->streams);
  323.   VEC_quick_push (ui_filep, data->streams, stream);

  324.   return old;
  325. }