fix record "run" regression
[platform/upstream/binutils.git] / gdb / cli-out.c
1 /* Output generating routines for GDB CLI.
2
3    Copyright (C) 1999-2014 Free Software Foundation, Inc.
4
5    Contributed by Cygnus Solutions.
6    Written by Fernando Nasser for Cygnus.
7
8    This file is part of GDB.
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
23 #include "defs.h"
24 #include "ui-out.h"
25 #include "cli-out.h"
26 #include <string.h>
27 #include "gdb_assert.h"
28 #include "vec.h"
29
30 typedef struct cli_ui_out_data cli_out_data;
31
32
33 /* Prototypes for local functions */
34
35 static void cli_text (struct ui_out *uiout, const char *string);
36
37 static void field_separator (void);
38
39 static void out_field_fmt (struct ui_out *uiout, int fldno,
40                            const char *fldname,
41                            const char *format,...) ATTRIBUTE_PRINTF (4, 5);
42
43 /* The destructor.  */
44
45 static void
46 cli_uiout_dtor (struct ui_out *ui_out)
47 {
48   cli_out_data *data = ui_out_data (ui_out);
49
50   VEC_free (ui_filep, data->streams);
51   xfree (data);
52 }
53
54 /* These are the CLI output functions */
55
56 /* Mark beginning of a table */
57
58 static void
59 cli_table_begin (struct ui_out *uiout, int nbrofcols,
60                  int nr_rows,
61                  const char *tblid)
62 {
63   cli_out_data *data = ui_out_data (uiout);
64
65   if (nr_rows == 0)
66     data->suppress_output = 1;
67   else
68     /* Only the table suppresses the output and, fortunately, a table
69        is not a recursive data structure.  */
70     gdb_assert (data->suppress_output == 0);
71 }
72
73 /* Mark beginning of a table body */
74
75 static void
76 cli_table_body (struct ui_out *uiout)
77 {
78   cli_out_data *data = ui_out_data (uiout);
79
80   if (data->suppress_output)
81     return;
82   /* first, close the table header line */
83   cli_text (uiout, "\n");
84 }
85
86 /* Mark end of a table */
87
88 static void
89 cli_table_end (struct ui_out *uiout)
90 {
91   cli_out_data *data = ui_out_data (uiout);
92
93   data->suppress_output = 0;
94 }
95
96 /* Specify table header */
97
98 static void
99 cli_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
100                   const char *col_name,
101                   const char *colhdr)
102 {
103   cli_out_data *data = ui_out_data (uiout);
104
105   if (data->suppress_output)
106     return;
107
108   /* Always go through the function pointer (virtual function call).
109      We may have been extended.  */
110   uo_field_string (uiout, 0, width, alignment, 0, colhdr);
111 }
112
113 /* Mark beginning of a list */
114
115 static void
116 cli_begin (struct ui_out *uiout,
117            enum ui_out_type type,
118            int level,
119            const char *id)
120 {
121   cli_out_data *data = ui_out_data (uiout);
122
123   if (data->suppress_output)
124     return;
125 }
126
127 /* Mark end of a list */
128
129 static void
130 cli_end (struct ui_out *uiout,
131          enum ui_out_type type,
132          int level)
133 {
134   cli_out_data *data = ui_out_data (uiout);
135
136   if (data->suppress_output)
137     return;
138 }
139
140 /* output an int field */
141
142 static void
143 cli_field_int (struct ui_out *uiout, int fldno, int width,
144                enum ui_align alignment,
145                const char *fldname, int value)
146 {
147   char buffer[20];      /* FIXME: how many chars long a %d can become? */
148   cli_out_data *data = ui_out_data (uiout);
149
150   if (data->suppress_output)
151     return;
152   xsnprintf (buffer, sizeof (buffer), "%d", value);
153
154   /* Always go through the function pointer (virtual function call).
155      We may have been extended.  */
156   uo_field_string (uiout, fldno, width, alignment, fldname, buffer);
157 }
158
159 /* used to ommit a field */
160
161 static void
162 cli_field_skip (struct ui_out *uiout, int fldno, int width,
163                 enum ui_align alignment,
164                 const char *fldname)
165 {
166   cli_out_data *data = ui_out_data (uiout);
167
168   if (data->suppress_output)
169     return;
170
171   /* Always go through the function pointer (virtual function call).
172      We may have been extended.  */
173   uo_field_string (uiout, fldno, width, alignment, fldname, "");
174 }
175
176 /* other specific cli_field_* end up here so alignment and field
177    separators are both handled by cli_field_string */
178
179 static void
180 cli_field_string (struct ui_out *uiout,
181                   int fldno,
182                   int width,
183                   enum ui_align align,
184                   const char *fldname,
185                   const char *string)
186 {
187   int before = 0;
188   int after = 0;
189   cli_out_data *data = ui_out_data (uiout);
190
191   if (data->suppress_output)
192     return;
193
194   if ((align != ui_noalign) && string)
195     {
196       before = width - strlen (string);
197       if (before <= 0)
198         before = 0;
199       else
200         {
201           if (align == ui_right)
202             after = 0;
203           else if (align == ui_left)
204             {
205               after = before;
206               before = 0;
207             }
208           else
209             /* ui_center */
210             {
211               after = before / 2;
212               before -= after;
213             }
214         }
215     }
216
217   if (before)
218     ui_out_spaces (uiout, before);
219   if (string)
220     out_field_fmt (uiout, fldno, fldname, "%s", string);
221   if (after)
222     ui_out_spaces (uiout, after);
223
224   if (align != ui_noalign)
225     field_separator ();
226 }
227
228 /* This is the only field function that does not align.  */
229
230 static void ATTRIBUTE_PRINTF (6, 0)
231 cli_field_fmt (struct ui_out *uiout, int fldno,
232                int width, enum ui_align align,
233                const char *fldname,
234                const char *format,
235                va_list args)
236 {
237   cli_out_data *data = ui_out_data (uiout);
238   struct ui_file *stream;
239
240   if (data->suppress_output)
241     return;
242
243   stream = VEC_last (ui_filep, data->streams);
244   vfprintf_filtered (stream, format, args);
245
246   if (align != ui_noalign)
247     field_separator ();
248 }
249
250 static void
251 cli_spaces (struct ui_out *uiout, int numspaces)
252 {
253   cli_out_data *data = ui_out_data (uiout);
254   struct ui_file *stream;
255
256   if (data->suppress_output)
257     return;
258
259   stream = VEC_last (ui_filep, data->streams);
260   print_spaces_filtered (numspaces, stream);
261 }
262
263 static void
264 cli_text (struct ui_out *uiout, const char *string)
265 {
266   cli_out_data *data = ui_out_data (uiout);
267   struct ui_file *stream;
268
269   if (data->suppress_output)
270     return;
271
272   stream = VEC_last (ui_filep, data->streams);
273   fputs_filtered (string, stream);
274 }
275
276 static void ATTRIBUTE_PRINTF (3, 0)
277 cli_message (struct ui_out *uiout, int verbosity,
278              const char *format, va_list args)
279 {
280   cli_out_data *data = ui_out_data (uiout);
281
282   if (data->suppress_output)
283     return;
284
285   if (ui_out_get_verblvl (uiout) >= verbosity)
286     {
287       struct ui_file *stream = VEC_last (ui_filep, data->streams);
288
289       vfprintf_unfiltered (stream, format, args);
290     }
291 }
292
293 static void
294 cli_wrap_hint (struct ui_out *uiout, char *identstring)
295 {
296   cli_out_data *data = ui_out_data (uiout);
297
298   if (data->suppress_output)
299     return;
300   wrap_here (identstring);
301 }
302
303 static void
304 cli_flush (struct ui_out *uiout)
305 {
306   cli_out_data *data = ui_out_data (uiout);
307   struct ui_file *stream = VEC_last (ui_filep, data->streams);
308
309   gdb_flush (stream);
310 }
311
312 /* OUTSTREAM as non-NULL will push OUTSTREAM on the stack of output streams
313    and make it therefore active.  OUTSTREAM as NULL will pop the last pushed
314    output stream; it is an internal error if it does not exist.  */
315
316 static int
317 cli_redirect (struct ui_out *uiout, struct ui_file *outstream)
318 {
319   cli_out_data *data = ui_out_data (uiout);
320
321   if (outstream != NULL)
322     VEC_safe_push (ui_filep, data->streams, outstream);
323   else
324     VEC_pop (ui_filep, data->streams);
325
326   return 0;
327 }
328
329 /* local functions */
330
331 /* Like cli_field_fmt, but takes a variable number of args
332    and makes a va_list and does not insert a separator.  */
333
334 /* VARARGS */
335 static void
336 out_field_fmt (struct ui_out *uiout, int fldno,
337                const char *fldname,
338                const char *format,...)
339 {
340   cli_out_data *data = ui_out_data (uiout);
341   struct ui_file *stream = VEC_last (ui_filep, data->streams);
342   va_list args;
343
344   va_start (args, format);
345   vfprintf_filtered (stream, format, args);
346
347   va_end (args);
348 }
349
350 /* Access to ui_out format private members.  */
351
352 static void
353 field_separator (void)
354 {
355   cli_out_data *data = ui_out_data (current_uiout);
356   struct ui_file *stream = VEC_last (ui_filep, data->streams);
357
358   fputc_filtered (' ', stream);
359 }
360
361 /* This is the CLI ui-out implementation functions vector */
362
363 const struct ui_out_impl cli_ui_out_impl =
364 {
365   cli_table_begin,
366   cli_table_body,
367   cli_table_end,
368   cli_table_header,
369   cli_begin,
370   cli_end,
371   cli_field_int,
372   cli_field_skip,
373   cli_field_string,
374   cli_field_fmt,
375   cli_spaces,
376   cli_text,
377   cli_message,
378   cli_wrap_hint,
379   cli_flush,
380   cli_redirect,
381   cli_uiout_dtor,
382   0, /* Does not need MI hacks (i.e. needs CLI hacks).  */
383 };
384
385 /* Constructor for a `cli_out_data' object.  */
386
387 void
388 cli_out_data_ctor (cli_out_data *self, struct ui_file *stream)
389 {
390   gdb_assert (stream != NULL);
391
392   self->streams = NULL;
393   VEC_safe_push (ui_filep, self->streams, stream);
394
395   self->suppress_output = 0;
396 }
397
398 /* Initialize private members at startup.  */
399
400 struct ui_out *
401 cli_out_new (struct ui_file *stream)
402 {
403   int flags = ui_source_list;
404   cli_out_data *data = XNEW (cli_out_data);
405
406   cli_out_data_ctor (data, stream);
407   return ui_out_new (&cli_ui_out_impl, data, flags);
408 }
409
410 struct ui_file *
411 cli_out_set_stream (struct ui_out *uiout, struct ui_file *stream)
412 {
413   cli_out_data *data = ui_out_data (uiout);
414   struct ui_file *old;
415   
416   old = VEC_pop (ui_filep, data->streams);
417   VEC_quick_push (ui_filep, data->streams, stream);
418
419   return old;
420 }