GDB (xrefs)
/tmp/gdb-8.1/gdb/ui-out.c
Go to the documentation of this file.
1 /* Output generating routines for GDB.
2 
3  Copyright (C) 1999-2018 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 "expression.h" /* For language.h */
25 #include "language.h"
26 #include "ui-out.h"
27 
28 #include <vector>
29 #include <memory>
30 #include <string>
31 #include <memory>
32 
33 namespace {
34 
35 /* A header of a ui_out_table. */
36 
37 class ui_out_hdr
38 {
39  public:
40 
41  explicit ui_out_hdr (int number, int min_width, ui_align alignment,
42  const std::string &name, const std::string &header)
43  : m_number (number),
44  m_min_width (min_width),
45  m_alignment (alignment),
46  m_name (name),
47  m_header (header)
48  {
49  }
50 
51  int number () const
52  {
53  return m_number;
54  }
55 
56  int min_width () const
57  {
58  return m_min_width;
59  }
60 
61  ui_align alignment () const
62  {
63  return m_alignment;
64  }
65 
66  const std::string &header () const
67  {
68  return m_header;
69  }
70 
71  const std::string &name () const
72  {
73  return m_name;
74  }
75 
76  private:
77 
78  /* The number of the table column this header represents, 1-based. */
79  int m_number;
80 
81  /* Minimal column width in characters. May or may not be applicable,
82  depending on the actual implementation of ui_out. */
83  int m_min_width;
84 
85  /* Alignment of the content in the column. May or may not be applicable,
86  depending on the actual implementation of ui_out. */
87  ui_align m_alignment;
88 
89  /* Internal column name, used to internally refer to the column. */
90  std::string m_name;
91 
92  /* Printed header text of the column. */
93  std::string m_header;
94 };
95 
96 } // namespace
97 
98 /* A level of nesting (either a list or a tuple) in a ui_out output. */
99 
101 {
102  public:
103 
105  : m_type (type),
106  m_field_count (0)
107  {
108  }
109 
110  ui_out_type type () const
111  {
112  return m_type;
113  }
114 
115  int field_count () const
116  {
117  return m_field_count;
118  }
119 
121  {
122  m_field_count++;
123  }
124 
125  private:
126 
127  /* The type of this level. */
129 
130  /* Count each field; the first element is for non-list fields. */
132 };
133 
134 /* Tables are special. Maintain a separate structure that tracks
135  their state. At present an output can only contain a single table
136  but that restriction might eventually be lifted. */
137 
139 {
140  public:
141 
142  /* States (steps) of a table generation. */
143 
144  enum class state
145  {
146  /* We are generating the table headers. */
147  HEADERS,
148 
149  /* We are generating the table body. */
150  BODY,
151  };
152 
153  explicit ui_out_table (int entry_level, int nr_cols, const std::string &id)
154  : m_state (state::HEADERS),
156  m_nr_cols (nr_cols),
157  m_id (id)
158  {
159  }
160 
161  /* Start building the body of the table. */
162 
163  void start_body ();
164 
165  /* Add a new header to the table. */
166 
167  void append_header (int width, ui_align alignment,
168  const std::string &col_name, const std::string &col_hdr);
169 
170  void start_row ();
171 
172  /* Extract the format information for the next header and advance
173  the header iterator. Return false if there was no next header. */
174 
175  bool get_next_header (int *colno, int *width, ui_align *alignment,
176  const char **col_hdr);
177 
178  bool query_field (int colno, int *width, int *alignment,
179  const char **col_name) const;
180 
181  state current_state () const;
182 
183  int entry_level () const;
184 
185  private:
186 
188 
189  /* The level at which each entry of the table is to be found. A row
190  (a tuple) is made up of entries. Consequently ENTRY_LEVEL is one
191  above that of the table. */
193 
194  /* Number of table columns (as specified in the table_begin call). */
196 
197  /* String identifying the table (as specified in the table_begin
198  call). */
200 
201  /* Pointers to the column headers. */
202  std::vector<std::unique_ptr<ui_out_hdr>> m_headers;
203 
204  /* Iterator over the headers vector, used when printing successive fields. */
205  std::vector<std::unique_ptr<ui_out_hdr>>::const_iterator m_headers_iterator;
206 };
207 
208 /* See ui-out.h. */
209 
211 {
212  if (m_state != state::HEADERS)
213  internal_error (__FILE__, __LINE__,
214  _("extra table_body call not allowed; there must be only "
215  "one table_body after a table_begin and before a "
216  "table_end."));
217 
218  /* Check if the number of defined headers matches the number of expected
219  columns. */
220  if (m_headers.size () != m_nr_cols)
221  internal_error (__FILE__, __LINE__,
222  _("number of headers differ from number of table "
223  "columns."));
224 
226  m_headers_iterator = m_headers.begin ();
227 }
228 
229 /* See ui-out.h. */
230 
231 void ui_out_table::append_header (int width, ui_align alignment,
232  const std::string &col_name,
233  const std::string &col_hdr)
234 {
235  if (m_state != state::HEADERS)
236  internal_error (__FILE__, __LINE__,
237  _("table header must be specified after table_begin and "
238  "before table_body."));
239 
240  std::unique_ptr<ui_out_hdr> header (new ui_out_hdr (m_headers.size () + 1,
241  width, alignment,
242  col_name, col_hdr));
243 
244  m_headers.push_back (std::move (header));
245 }
246 
247 /* See ui-out.h. */
248 
250 {
251  m_headers_iterator = m_headers.begin ();
252 }
253 
254 /* See ui-out.h. */
255 
256 bool ui_out_table::get_next_header (int *colno, int *width, ui_align *alignment,
257  const char **col_hdr)
258 {
259  /* There may be no headers at all or we may have used all columns. */
260  if (m_headers_iterator == m_headers.end ())
261  return false;
262 
263  ui_out_hdr *hdr = m_headers_iterator->get ();
264 
265  *colno = hdr->number ();
266  *width = hdr->min_width ();
267  *alignment = hdr->alignment ();
268  *col_hdr = hdr->header ().c_str ();
269 
270  /* Advance the header pointer to the next entry. */
272 
273  return true;
274 }
275 
276 /* See ui-out.h. */
277 
278 bool ui_out_table::query_field (int colno, int *width, int *alignment,
279  const char **col_name) const
280 {
281  /* Column numbers are 1-based, so convert to 0-based index. */
282  int index = colno - 1;
283 
284  if (index >= 0 && index < m_headers.size ())
285  {
286  ui_out_hdr *hdr = m_headers[index].get ();
287 
288  gdb_assert (colno == hdr->number ());
289 
290  *width = hdr->min_width ();
291  *alignment = hdr->alignment ();
292  *col_name = hdr->name ().c_str ();
293 
294  return true;
295  }
296  else
297  return false;
298 }
299 
300 /* See ui-out.h. */
301 
303 {
304  return m_state;
305 }
306 
307 /* See ui-out.h. */
308 
310 {
311  return m_entry_level;
312 }
313 
314 int
316 {
317  return m_levels.size ();
318 }
319 
320 /* The current (inner most) level. */
321 
322 ui_out_level *
324 {
325  return m_levels.back ().get ();
326 }
327 
328 /* Create a new level, of TYPE. */
329 void
331 {
332  std::unique_ptr<ui_out_level> level (new ui_out_level (type));
333 
334  m_levels.push_back (std::move (level));
335 }
336 
337 /* Discard the current level. TYPE is the type of the level being
338  discarded. */
339 void
341 {
342  /* We had better not underflow the buffer. */
343  gdb_assert (m_levels.size () > 0);
344  gdb_assert (current_level ()->type () == type);
345 
346  m_levels.pop_back ();
347 }
348 
349 /* Mark beginning of a table. */
350 
351 void
352 ui_out::table_begin (int nr_cols, int nr_rows, const std::string &tblid)
353 {
354  if (m_table_up != nullptr)
355  internal_error (__FILE__, __LINE__,
356  _("tables cannot be nested; table_begin found before \
357 previous table_end."));
358 
359  m_table_up.reset (new ui_out_table (level () + 1, nr_cols, tblid));
360 
361  do_table_begin (nr_cols, nr_rows, tblid.c_str ());
362 }
363 
364 void
365 ui_out::table_header (int width, ui_align alignment,
366  const std::string &col_name, const std::string &col_hdr)
367 {
368  if (m_table_up == nullptr)
369  internal_error (__FILE__, __LINE__,
370  _("table_header outside a table is not valid; it must be \
371 after a table_begin and before a table_body."));
372 
373  m_table_up->append_header (width, alignment, col_name, col_hdr);
374 
375  do_table_header (width, alignment, col_name, col_hdr);
376 }
377 
378 void
380 {
381  if (m_table_up == nullptr)
382  internal_error (__FILE__, __LINE__,
383  _("table_body outside a table is not valid; it must be "
384  "after a table_begin and before a table_end."));
385 
386  m_table_up->start_body ();
387 
388  do_table_body ();
389 }
390 
391 void
393 {
394  if (m_table_up == nullptr)
395  internal_error (__FILE__, __LINE__,
396  _("misplaced table_end or missing table_begin."));
397 
398  do_table_end ();
399 
400  m_table_up = nullptr;
401 }
402 
403 void
404 ui_out::begin (ui_out_type type, const char *id)
405 {
406  /* Be careful to verify the ``field'' before the new tuple/list is
407  pushed onto the stack. That way the containing list/table/row is
408  verified and not the newly created tuple/list. This verification
409  is needed (at least) for the case where a table row entry
410  contains either a tuple/list. For that case bookkeeping such as
411  updating the column count or advancing to the next heading still
412  needs to be performed. */
413  {
414  int fldno;
415  int width;
416  ui_align align;
417 
418  verify_field (&fldno, &width, &align);
419  }
420 
421  push_level (type);
422 
423  /* If the push puts us at the same level as a table row entry, we've
424  got a new table row. Put the header pointer back to the start. */
425  if (m_table_up != nullptr
426  && m_table_up->current_state () == ui_out_table::state::BODY
427  && m_table_up->entry_level () == level ())
428  m_table_up->start_row ();
429 
430  do_begin (type, id);
431 }
432 
433 void
435 {
436  pop_level (type);
437 
438  do_end (type);
439 }
440 
442 {
443  struct ui_out *uiout;
445 };
446 
447 static void
448 do_cleanup_end (void *data)
449 {
450  struct ui_out_end_cleanup_data *end_cleanup_data
451  = (struct ui_out_end_cleanup_data *) data;
452 
453  end_cleanup_data->uiout->end (end_cleanup_data->type);
454  xfree (end_cleanup_data);
455 }
456 
457 static struct cleanup *
459  enum ui_out_type type)
460 {
461  struct ui_out_end_cleanup_data *end_cleanup_data;
462 
463  end_cleanup_data = XNEW (struct ui_out_end_cleanup_data);
464  end_cleanup_data->uiout = uiout;
465  end_cleanup_data->type = type;
466  return make_cleanup (do_cleanup_end, end_cleanup_data);
467 }
468 
469 struct cleanup *
471  const char *id)
472 {
473  uiout->begin (ui_out_type_tuple, id);
475 }
476 
477 struct cleanup *
479  const char *id)
480 {
481  uiout->begin (ui_out_type_list, id);
483 }
484 
485 void
486 ui_out::field_int (const char *fldname, int value)
487 {
488  int fldno;
489  int width;
490  ui_align align;
491 
492  verify_field (&fldno, &width, &align);
493 
494  do_field_int (fldno, width, align, fldname, value);
495 }
496 
497 void
498 ui_out::field_fmt_int (int input_width, ui_align input_align,
499  const char *fldname, int value)
500 {
501  int fldno;
502  int width;
503  ui_align align;
504 
505  verify_field (&fldno, &width, &align);
506 
507  do_field_int (fldno, input_width, input_align, fldname, value);
508 }
509 
510 /* Documented in ui-out.h. */
511 
512 void
513 ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch,
514  CORE_ADDR address)
515 {
516  field_string (fldname, print_core_address (gdbarch, address));
517 }
518 
519 void
520 ui_out::field_stream (const char *fldname, string_file &stream)
521 {
522  if (!stream.empty ())
523  field_string (fldname, stream.c_str ());
524  else
525  field_skip (fldname);
526  stream.clear ();
527 }
528 
529 /* Used to omit a field. */
530 
531 void
532 ui_out::field_skip (const char *fldname)
533 {
534  int fldno;
535  int width;
536  ui_align align;
537 
538  verify_field (&fldno, &width, &align);
539 
540  do_field_skip (fldno, width, align, fldname);
541 }
542 
543 void
544 ui_out::field_string (const char *fldname, const char *string)
545 {
546  int fldno;
547  int width;
548  ui_align align;
549 
550  verify_field (&fldno, &width, &align);
551 
552  do_field_string (fldno, width, align, fldname, string);
553 }
554 
555 /* VARARGS */
556 void
557 ui_out::field_fmt (const char *fldname, const char *format, ...)
558 {
559  va_list args;
560  int fldno;
561  int width;
562  ui_align align;
563 
564  /* Will not align, but has to call anyway. */
565  verify_field (&fldno, &width, &align);
566 
567  va_start (args, format);
568 
569  do_field_fmt (fldno, width, align, fldname, format, args);
570 
571  va_end (args);
572 }
573 
574 void
575 ui_out::spaces (int numspaces)
576 {
577  do_spaces (numspaces);
578 }
579 
580 void
581 ui_out::text (const char *string)
582 {
583  do_text (string);
584 }
585 
586 void
587 ui_out::message (const char *format, ...)
588 {
589  va_list args;
590 
591  va_start (args, format);
592  do_message (format, args);
593  va_end (args);
594 }
595 
596 void
597 ui_out::wrap_hint (const char *identstring)
598 {
599  do_wrap_hint (identstring);
600 }
601 
602 void
604 {
605  do_flush ();
606 }
607 
608 void
610 {
611  do_redirect (outstream);
612 }
613 
614 /* Test the flags against the mask given. */
615 ui_out_flags
616 ui_out::test_flags (ui_out_flags mask)
617 {
618  return m_flags & mask;
619 }
620 
621 bool
623 {
624  return do_is_mi_like_p ();
625 }
626 
627 /* Verify that the field/tuple/list is correctly positioned. Return
628  the field number and corresponding alignment (if
629  available/applicable). */
630 
631 void
632 ui_out::verify_field (int *fldno, int *width, ui_align *align)
633 {
634  ui_out_level *current = current_level ();
635  const char *text;
636 
637  if (m_table_up != nullptr
638  && m_table_up->current_state () != ui_out_table::state::BODY)
639  {
640  internal_error (__FILE__, __LINE__,
641  _("table_body missing; table fields must be \
642 specified after table_body and inside a list."));
643  }
644 
645  current->inc_field_count ();
646 
647  if (m_table_up != nullptr
648  && m_table_up->current_state () == ui_out_table::state::BODY
649  && m_table_up->entry_level () == level ()
650  && m_table_up->get_next_header (fldno, width, align, &text))
651  {
652  if (*fldno != current->field_count ())
653  internal_error (__FILE__, __LINE__,
654  _("ui-out internal error in handling headers."));
655  }
656  else
657  {
658  *width = 0;
659  *align = ui_noalign;
660  *fldno = current->field_count ();
661  }
662 }
663 
664 /* Access table field parameters. */
665 
666 bool
667 ui_out::query_table_field (int colno, int *width, int *alignment,
668  const char **col_name)
669 {
670  if (m_table_up == nullptr)
671  return false;
672 
673  return m_table_up->query_field (colno, width, alignment, col_name);
674 }
675 
676 /* The constructor. */
677 
678 ui_out::ui_out (ui_out_flags flags)
679 : m_flags (flags)
680 {
681  /* Create the ui-out level #1, the default level. */
683 }
684 
686 {
687 }
const char * string
Definition: signals.c:50
virtual void virtual void do_spaces(int numspaces)=0
static void do_cleanup_end(void *data)
Definition: ui-out.c:448
virtual void do_end(ui_out_type type)=0
void field_core_addr(const char *fldname, struct gdbarch *gdbarch, CORE_ADDR address)
Definition: ui-out.c:513
void field_string(const char *fldname, const char *string)
Definition: ui-out.c:544
bfd_vma CORE_ADDR
Definition: common-types.h:41
void start_row()
Definition: ui-out.c:249
void pop_level(ui_out_type type)
Definition: ui-out.c:340
void xfree(void *)
ui_out_flags test_flags(ui_out_flags mask)
Definition: ui-out.c:616
static struct cleanup * make_cleanup_ui_out_end(struct ui_out *uiout, enum ui_out_type type)
Definition: ui-out.c:458
ui_out_level * current_level() const
Definition: ui-out.c:323
void void wrap_hint(const char *identstring)
Definition: ui-out.c:597
std::vector< std::unique_ptr< ui_out_level > > m_levels
Definition: ui-out.h:175
void verify_field(int *fldno, int *width, ui_align *align)
Definition: ui-out.c:632
int level() const
Definition: ui-out.c:315
ui_out_type type() const
Definition: ui-out.c:110
bool empty() const
Definition: ui-file.h:139
void field_skip(const char *fldname)
Definition: ui-out.c:532
virtual void do_begin(ui_out_type type, const char *id)=0
void internal_error(const char *file, int line, const char *fmt,...)
Definition: errors.c:50
void table_header(int width, ui_align align, const std::string &col_name, const std::string &col_hdr)
Definition: ui-out.c:365
virtual void do_field_fmt(int fldno, int width, ui_align align, const char *fldname, const char *format, va_list args) ATTRIBUTE_PRINTF(6
struct ui_out * uiout
Definition: ui-out.c:443
virtual void do_table_header(int width, ui_align align, const std::string &col_name, const std::string &col_hdr)=0
bool query_field(int colno, int *width, int *alignment, const char **col_name) const
Definition: ui-out.c:278
#define _(String)
Definition: gdb_locale.h:35
std::unique_ptr< ui_out_table > m_table_up
Definition: ui-out.h:178
void text(const char *string)
Definition: ui-out.c:581
void start_body()
Definition: ui-out.c:210
virtual void virtual void do_wrap_hint(const char *identstring)=0
#define XNEW(T)
Definition: poison.h:109
ui_out(ui_out_flags flags=0)
Definition: ui-out.c:678
int field_count() const
Definition: ui-out.c:115
mach_port_t kern_return_t mach_port_t msgports mach_port_t kern_return_t pid_t pid mach_port_t kern_return_t mach_port_t task mach_port_t kern_return_t int flags
Definition: gnu-nat.c:1891
void append_header(int width, ui_align alignment, const std::string &col_name, const std::string &col_hdr)
Definition: ui-out.c:231
const char *const name
Definition: aarch64-tdep.c:76
int m_entry_level
Definition: ui-out.c:192
ui_out_level(ui_out_type type)
Definition: ui-out.c:104
enum ui_out_type type
Definition: ui-out.c:444
void end(ui_out_type type)
Definition: ui-out.c:434
void redirect(ui_file *outstream)
Definition: ui-out.c:609
void inc_field_count()
Definition: ui-out.c:120
struct cleanup * make_cleanup_ui_out_list_begin_end(struct ui_out *uiout, const char *id)
Definition: ui-out.c:478
struct cleanup * make_cleanup_ui_out_tuple_begin_end(struct ui_out *uiout, const char *id)
Definition: ui-out.c:470
void table_end()
Definition: ui-out.c:392
virtual bool do_is_mi_like_p()
Definition: ui-out.h:167
struct cleanup * make_cleanup(make_cleanup_ftype *function, void *arg)
Definition: cleanups.c:116
std::string m_id
Definition: ui-out.c:199
Definition: gdbtypes.h:749
ui_out_table(int entry_level, int nr_cols, const std::string &id)
Definition: ui-out.c:153
virtual ~ui_out()
Definition: ui-out.c:685
virtual void do_field_skip(int fldno, int width, ui_align align, const char *fldname)=0
void clear()
Definition: ui-file.h:140
static const char * type
Definition: language.c:113
void field_stream(const char *fldname, string_file &stream)
Definition: ui-out.c:520
ui_out_type m_type
Definition: ui-out.c:128
void void spaces(int numspaces)
Definition: ui-out.c:575
#define gdb_assert(expr)
Definition: gdb_assert.h:32
Definition: value.c:169
Definition: ui-out.h:77
int m_nr_cols
Definition: ui-out.c:195
virtual void do_table_begin(int nbrofcols, int nr_rows, const char *tblid)=0
virtual void do_flush()=0
int entry_level() const
Definition: ui-out.c:309
virtual void do_field_string(int fldno, int width, ui_align align, const char *fldname, const char *string)=0
ui_out_flags m_flags
Definition: ui-out.h:172
bool query_table_field(int colno, int *width, int *alignment, const char **col_name)
Definition: ui-out.c:667
state m_state
Definition: ui-out.c:187
const char * c_str() const
Definition: ui-file.h:137
ui_align
Definition: ui-out.h:42
void field_int(const char *fldname, int value)
Definition: ui-out.c:486
void table_body()
Definition: ui-out.c:379
virtual void do_redirect(struct ui_file *outstream)=0
void message(const char *format,...) ATTRIBUTE_PRINTF(2
Definition: ui-out.c:587
std::vector< std::unique_ptr< ui_out_hdr > >::const_iterator m_headers_iterator
Definition: ui-out.c:205
const char * print_core_address(struct gdbarch *gdbarch, CORE_ADDR address)
Definition: utils.c:2766
state current_state() const
Definition: ui-out.c:302
virtual void do_text(const char *string)=0
virtual void do_field_int(int fldno, int width, ui_align align, const char *fldname, int value)=0
void field_fmt_int(int width, ui_align align, const char *fldname, int value)
Definition: ui-out.c:498
std::vector< std::unique_ptr< ui_out_hdr > > m_headers
Definition: ui-out.c:202
int m_field_count
Definition: ui-out.c:131
ui_out_type
Definition: ui-out.h:63
void flush()
Definition: ui-out.c:603
virtual void do_table_body()=0
virtual void do_table_end()=0
void begin(ui_out_type type, const char *id)
Definition: ui-out.c:404
void push_level(ui_out_type type)
Definition: ui-out.c:330
virtual void do_message(const char *format, va_list args) ATTRIBUTE_PRINTF(2
bool is_mi_like_p()
Definition: ui-out.c:622
bool get_next_header(int *colno, int *width, ui_align *alignment, const char **col_hdr)
Definition: ui-out.c:256
void field_fmt(const char *fldname, const char *format,...) ATTRIBUTE_PRINTF(3
Definition: ui-out.c:557
void table_begin(int nr_cols, int nr_rows, const std::string &tblid)
Definition: ui-out.c:352