GDB (API)
/home/stan/gdb/src/gdb/cli-out.c
Go to the documentation of this file.
00001 /* Output generating routines for GDB CLI.
00002 
00003    Copyright (C) 1999-2013 Free Software Foundation, Inc.
00004 
00005    Contributed by Cygnus Solutions.
00006    Written by Fernando Nasser for Cygnus.
00007 
00008    This file is part of GDB.
00009 
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 3 of the License, or
00013    (at your option) any later version.
00014 
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License
00021    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00022 
00023 #include "defs.h"
00024 #include "ui-out.h"
00025 #include "cli-out.h"
00026 #include "gdb_string.h"
00027 #include "gdb_assert.h"
00028 #include "vec.h"
00029 
00030 typedef struct cli_ui_out_data cli_out_data;
00031 
00032 
00033 /* Prototypes for local functions */
00034 
00035 static void cli_text (struct ui_out *uiout, const char *string);
00036 
00037 static void field_separator (void);
00038 
00039 static void out_field_fmt (struct ui_out *uiout, int fldno,
00040                            const char *fldname,
00041                            const char *format,...) ATTRIBUTE_PRINTF (4, 5);
00042 
00043 /* These are the CLI output functions */
00044 
00045 /* Mark beginning of a table */
00046 
00047 static void
00048 cli_table_begin (struct ui_out *uiout, int nbrofcols,
00049                  int nr_rows,
00050                  const char *tblid)
00051 {
00052   cli_out_data *data = ui_out_data (uiout);
00053 
00054   if (nr_rows == 0)
00055     data->suppress_output = 1;
00056   else
00057     /* Only the table suppresses the output and, fortunately, a table
00058        is not a recursive data structure.  */
00059     gdb_assert (data->suppress_output == 0);
00060 }
00061 
00062 /* Mark beginning of a table body */
00063 
00064 static void
00065 cli_table_body (struct ui_out *uiout)
00066 {
00067   cli_out_data *data = ui_out_data (uiout);
00068 
00069   if (data->suppress_output)
00070     return;
00071   /* first, close the table header line */
00072   cli_text (uiout, "\n");
00073 }
00074 
00075 /* Mark end of a table */
00076 
00077 static void
00078 cli_table_end (struct ui_out *uiout)
00079 {
00080   cli_out_data *data = ui_out_data (uiout);
00081 
00082   data->suppress_output = 0;
00083 }
00084 
00085 /* Specify table header */
00086 
00087 static void
00088 cli_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
00089                   const char *col_name,
00090                   const char *colhdr)
00091 {
00092   cli_out_data *data = ui_out_data (uiout);
00093 
00094   if (data->suppress_output)
00095     return;
00096 
00097   /* Always go through the function pointer (virtual function call).
00098      We may have been extended.  */
00099   uo_field_string (uiout, 0, width, alignment, 0, colhdr);
00100 }
00101 
00102 /* Mark beginning of a list */
00103 
00104 static void
00105 cli_begin (struct ui_out *uiout,
00106            enum ui_out_type type,
00107            int level,
00108            const char *id)
00109 {
00110   cli_out_data *data = ui_out_data (uiout);
00111 
00112   if (data->suppress_output)
00113     return;
00114 }
00115 
00116 /* Mark end of a list */
00117 
00118 static void
00119 cli_end (struct ui_out *uiout,
00120          enum ui_out_type type,
00121          int level)
00122 {
00123   cli_out_data *data = ui_out_data (uiout);
00124 
00125   if (data->suppress_output)
00126     return;
00127 }
00128 
00129 /* output an int field */
00130 
00131 static void
00132 cli_field_int (struct ui_out *uiout, int fldno, int width,
00133                enum ui_align alignment,
00134                const char *fldname, int value)
00135 {
00136   char buffer[20];      /* FIXME: how many chars long a %d can become? */
00137   cli_out_data *data = ui_out_data (uiout);
00138 
00139   if (data->suppress_output)
00140     return;
00141   xsnprintf (buffer, sizeof (buffer), "%d", value);
00142 
00143   /* Always go through the function pointer (virtual function call).
00144      We may have been extended.  */
00145   uo_field_string (uiout, fldno, width, alignment, fldname, buffer);
00146 }
00147 
00148 /* used to ommit a field */
00149 
00150 static void
00151 cli_field_skip (struct ui_out *uiout, int fldno, int width,
00152                 enum ui_align alignment,
00153                 const char *fldname)
00154 {
00155   cli_out_data *data = ui_out_data (uiout);
00156 
00157   if (data->suppress_output)
00158     return;
00159 
00160   /* Always go through the function pointer (virtual function call).
00161      We may have been extended.  */
00162   uo_field_string (uiout, fldno, width, alignment, fldname, "");
00163 }
00164 
00165 /* other specific cli_field_* end up here so alignment and field
00166    separators are both handled by cli_field_string */
00167 
00168 static void
00169 cli_field_string (struct ui_out *uiout,
00170                   int fldno,
00171                   int width,
00172                   enum ui_align align,
00173                   const char *fldname,
00174                   const char *string)
00175 {
00176   int before = 0;
00177   int after = 0;
00178   cli_out_data *data = ui_out_data (uiout);
00179 
00180   if (data->suppress_output)
00181     return;
00182 
00183   if ((align != ui_noalign) && string)
00184     {
00185       before = width - strlen (string);
00186       if (before <= 0)
00187         before = 0;
00188       else
00189         {
00190           if (align == ui_right)
00191             after = 0;
00192           else if (align == ui_left)
00193             {
00194               after = before;
00195               before = 0;
00196             }
00197           else
00198             /* ui_center */
00199             {
00200               after = before / 2;
00201               before -= after;
00202             }
00203         }
00204     }
00205 
00206   if (before)
00207     ui_out_spaces (uiout, before);
00208   if (string)
00209     out_field_fmt (uiout, fldno, fldname, "%s", string);
00210   if (after)
00211     ui_out_spaces (uiout, after);
00212 
00213   if (align != ui_noalign)
00214     field_separator ();
00215 }
00216 
00217 /* This is the only field function that does not align.  */
00218 
00219 static void ATTRIBUTE_PRINTF (6, 0)
00220 cli_field_fmt (struct ui_out *uiout, int fldno,
00221                int width, enum ui_align align,
00222                const char *fldname,
00223                const char *format,
00224                va_list args)
00225 {
00226   cli_out_data *data = ui_out_data (uiout);
00227   struct ui_file *stream;
00228 
00229   if (data->suppress_output)
00230     return;
00231 
00232   stream = VEC_last (ui_filep, data->streams);
00233   vfprintf_filtered (stream, format, args);
00234 
00235   if (align != ui_noalign)
00236     field_separator ();
00237 }
00238 
00239 static void
00240 cli_spaces (struct ui_out *uiout, int numspaces)
00241 {
00242   cli_out_data *data = ui_out_data (uiout);
00243   struct ui_file *stream;
00244 
00245   if (data->suppress_output)
00246     return;
00247 
00248   stream = VEC_last (ui_filep, data->streams);
00249   print_spaces_filtered (numspaces, stream);
00250 }
00251 
00252 static void
00253 cli_text (struct ui_out *uiout, const char *string)
00254 {
00255   cli_out_data *data = ui_out_data (uiout);
00256   struct ui_file *stream;
00257 
00258   if (data->suppress_output)
00259     return;
00260 
00261   stream = VEC_last (ui_filep, data->streams);
00262   fputs_filtered (string, stream);
00263 }
00264 
00265 static void ATTRIBUTE_PRINTF (3, 0)
00266 cli_message (struct ui_out *uiout, int verbosity,
00267              const char *format, va_list args)
00268 {
00269   cli_out_data *data = ui_out_data (uiout);
00270 
00271   if (data->suppress_output)
00272     return;
00273 
00274   if (ui_out_get_verblvl (uiout) >= verbosity)
00275     {
00276       struct ui_file *stream = VEC_last (ui_filep, data->streams);
00277 
00278       vfprintf_unfiltered (stream, format, args);
00279     }
00280 }
00281 
00282 static void
00283 cli_wrap_hint (struct ui_out *uiout, char *identstring)
00284 {
00285   cli_out_data *data = ui_out_data (uiout);
00286 
00287   if (data->suppress_output)
00288     return;
00289   wrap_here (identstring);
00290 }
00291 
00292 static void
00293 cli_flush (struct ui_out *uiout)
00294 {
00295   cli_out_data *data = ui_out_data (uiout);
00296   struct ui_file *stream = VEC_last (ui_filep, data->streams);
00297 
00298   gdb_flush (stream);
00299 }
00300 
00301 /* OUTSTREAM as non-NULL will push OUTSTREAM on the stack of output streams
00302    and make it therefore active.  OUTSTREAM as NULL will pop the last pushed
00303    output stream; it is an internal error if it does not exist.  */
00304 
00305 static int
00306 cli_redirect (struct ui_out *uiout, struct ui_file *outstream)
00307 {
00308   cli_out_data *data = ui_out_data (uiout);
00309 
00310   if (outstream != NULL)
00311     VEC_safe_push (ui_filep, data->streams, outstream);
00312   else
00313     VEC_pop (ui_filep, data->streams);
00314 
00315   return 0;
00316 }
00317 
00318 /* local functions */
00319 
00320 /* Like cli_field_fmt, but takes a variable number of args
00321    and makes a va_list and does not insert a separator.  */
00322 
00323 /* VARARGS */
00324 static void
00325 out_field_fmt (struct ui_out *uiout, int fldno,
00326                const char *fldname,
00327                const char *format,...)
00328 {
00329   cli_out_data *data = ui_out_data (uiout);
00330   struct ui_file *stream = VEC_last (ui_filep, data->streams);
00331   va_list args;
00332 
00333   va_start (args, format);
00334   vfprintf_filtered (stream, format, args);
00335 
00336   va_end (args);
00337 }
00338 
00339 /* Access to ui_out format private members.  */
00340 
00341 static void
00342 field_separator (void)
00343 {
00344   cli_out_data *data = ui_out_data (current_uiout);
00345   struct ui_file *stream = VEC_last (ui_filep, data->streams);
00346 
00347   fputc_filtered (' ', stream);
00348 }
00349 
00350 /* This is the CLI ui-out implementation functions vector */
00351 
00352 /* FIXME: This can be initialized dynamically after default is set to
00353    handle initial output in main.c */
00354 
00355 struct ui_out_impl cli_ui_out_impl =
00356 {
00357   cli_table_begin,
00358   cli_table_body,
00359   cli_table_end,
00360   cli_table_header,
00361   cli_begin,
00362   cli_end,
00363   cli_field_int,
00364   cli_field_skip,
00365   cli_field_string,
00366   cli_field_fmt,
00367   cli_spaces,
00368   cli_text,
00369   cli_message,
00370   cli_wrap_hint,
00371   cli_flush,
00372   cli_redirect,
00373   0,
00374   0, /* Does not need MI hacks (i.e. needs CLI hacks).  */
00375 };
00376 
00377 /* Constructor for a `cli_out_data' object.  */
00378 
00379 void
00380 cli_out_data_ctor (cli_out_data *self, struct ui_file *stream)
00381 {
00382   gdb_assert (stream != NULL);
00383 
00384   self->streams = NULL;
00385   VEC_safe_push (ui_filep, self->streams, stream);
00386 
00387   self->suppress_output = 0;
00388 }
00389 
00390 /* Initialize private members at startup.  */
00391 
00392 struct ui_out *
00393 cli_out_new (struct ui_file *stream)
00394 {
00395   int flags = ui_source_list;
00396   cli_out_data *data = XMALLOC (cli_out_data);
00397 
00398   cli_out_data_ctor (data, stream);
00399   return ui_out_new (&cli_ui_out_impl, data, flags);
00400 }
00401 
00402 struct ui_file *
00403 cli_out_set_stream (struct ui_out *uiout, struct ui_file *stream)
00404 {
00405   cli_out_data *data = ui_out_data (uiout);
00406   struct ui_file *old;
00407   
00408   old = VEC_pop (ui_filep, data->streams);
00409   VEC_quick_push (ui_filep, data->streams, stream);
00410 
00411   return old;
00412 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines