Use std::string for ui_out_hdr's text fields
[external/binutils.git] / gdb / ui-out.c
1 /* Output generating routines for GDB.
2
3    Copyright (C) 1999-2016 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
32 /* table header structures */
33
34 struct ui_out_hdr
35   {
36     int colno;
37     int width;
38     enum ui_align alignment;
39     std::string col_name;
40     std::string col_hdr;
41   };
42
43 struct ui_out_level
44   {
45     /* Count each field; the first element is for non-list fields.  */
46     int field_count;
47     /* The type of this level.  */
48     enum ui_out_type type;
49   };
50
51
52 /* Tables are special.  Maintain a separate structure that tracks
53    their state.  At present an output can only contain a single table
54    but that restriction might eventually be lifted.  */
55
56 struct ui_out_table
57 {
58   /* If on, a table is being generated.  */
59   int flag;
60
61   /* If on, the body of a table is being generated.  If off, the table
62      header is being generated.  */
63   int body_flag;
64
65   /* The level at which each entry of the table is to be found.  A row
66      (a tuple) is made up of entries.  Consequently ENTRY_LEVEL is one
67      above that of the table.  */
68   int entry_level;
69
70   /* Number of table columns (as specified in the table_begin call).  */
71   int columns;
72
73   /* String identifying the table (as specified in the table_begin
74      call).  */
75   std::string id;
76
77   /* Pointers to the column headers.  */
78   std::vector<std::unique_ptr<ui_out_hdr>> headers;
79
80   /* Iterator over the headers vector, used when printing successive fields.  */
81   std::vector<std::unique_ptr<ui_out_hdr>>::const_iterator headers_iterator;
82
83 };
84
85
86 /* The ui_out structure */
87
88 struct ui_out
89   {
90     int flags;
91     /* Specific implementation of ui-out.  */
92     const struct ui_out_impl *impl;
93     void *data;
94
95     /* Current level.  */
96     int level;
97
98     /* Vector to store and track the ui-out levels.  */
99     std::vector<std::unique_ptr<ui_out_level>> levels;
100
101     /* A table, if any.  At present only a single table is supported.  */
102     struct ui_out_table table;
103   };
104
105 /* The current (inner most) level.  */
106 static struct ui_out_level *
107 current_level (struct ui_out *uiout)
108 {
109   return uiout->levels[uiout->level].get ();
110 }
111
112 /* Create a new level, of TYPE.  Return the new level's index.  */
113 static int
114 push_level (struct ui_out *uiout,
115             enum ui_out_type type)
116 {
117   std::unique_ptr<ui_out_level> current (new ui_out_level ());
118
119   current->field_count = 0;
120   current->type = type;
121
122   uiout->level++;
123   uiout->levels.push_back (std::move (current));
124
125   return uiout->level;
126 }
127
128 /* Discard the current level, return the discarded level's index.
129    TYPE is the type of the level being discarded.  */
130 static int
131 pop_level (struct ui_out *uiout,
132            enum ui_out_type type)
133 {
134   /* We had better not underflow the buffer.  */
135   gdb_assert (uiout->level > 0);
136   gdb_assert (current_level (uiout)->type == type);
137
138   uiout->levels.pop_back ();
139   uiout->level--;
140
141   return uiout->level + 1;
142 }
143
144 /* These are the interfaces to implementation functions.  */
145
146 static void uo_table_begin (struct ui_out *uiout, int nbrofcols,
147                             int nr_rows, const char *tblid);
148 static void uo_table_body (struct ui_out *uiout);
149 static void uo_table_end (struct ui_out *uiout);
150 static void uo_table_header (struct ui_out *uiout, int width,
151                              enum ui_align align,
152                              const std::string &col_name,
153                              const std::string &col_hdr);
154 static void uo_begin (struct ui_out *uiout,
155                       enum ui_out_type type,
156                       int level, const char *id);
157 static void uo_end (struct ui_out *uiout,
158                     enum ui_out_type type,
159                     int level);
160 static void uo_field_int (struct ui_out *uiout, int fldno, int width,
161                           enum ui_align align, const char *fldname, int value);
162 static void uo_field_skip (struct ui_out *uiout, int fldno, int width,
163                            enum ui_align align, const char *fldname);
164 static void uo_field_fmt (struct ui_out *uiout, int fldno, int width,
165                           enum ui_align align, const char *fldname,
166                           const char *format, va_list args)
167      ATTRIBUTE_PRINTF (6, 0);
168 static void uo_spaces (struct ui_out *uiout, int numspaces);
169 static void uo_text (struct ui_out *uiout, const char *string);
170 static void uo_message (struct ui_out *uiout,
171                         const char *format, va_list args)
172      ATTRIBUTE_PRINTF (2, 0);
173 static void uo_wrap_hint (struct ui_out *uiout, const char *identstring);
174 static void uo_flush (struct ui_out *uiout);
175 static int uo_redirect (struct ui_out *uiout, struct ui_file *outstream);
176
177 /* Prototypes for local functions */
178
179 static void append_header_to_list (struct ui_out *uiout, int width,
180                                    enum ui_align alignment,
181                                    const std::string &col_name,
182                                    const std::string &col_hdr);
183 static int get_next_header (struct ui_out *uiout, int *colno, int *width,
184                             enum ui_align *alignment, const char **col_hdr);
185 static void clear_header_list (struct ui_out *uiout);
186 static void clear_table (struct ui_out *uiout);
187 static void verify_field (struct ui_out *uiout, int *fldno, int *width,
188                           enum ui_align *align);
189
190 /* exported functions (ui_out API) */
191
192 /* Mark beginning of a table.  */
193
194 static void
195 ui_out_table_begin (struct ui_out *uiout, int nbrofcols,
196                     int nr_rows, const std::string &tblid)
197 {
198   if (uiout->table.flag)
199     internal_error (__FILE__, __LINE__,
200                     _("tables cannot be nested; table_begin found before \
201 previous table_end."));
202
203   uiout->table.flag = 1;
204   uiout->table.body_flag = 0;
205   uiout->table.entry_level = uiout->level + 1;
206   uiout->table.columns = nbrofcols;
207   uiout->table.id = tblid;
208
209   clear_header_list (uiout);
210
211   uo_table_begin (uiout, nbrofcols, nr_rows, uiout->table.id.c_str ());
212 }
213
214 void
215 ui_out_table_body (struct ui_out *uiout)
216 {
217   if (!uiout->table.flag)
218     internal_error (__FILE__, __LINE__,
219                     _("table_body outside a table is not valid; it must be \
220 after a table_begin and before a table_end."));
221   if (uiout->table.body_flag)
222     internal_error (__FILE__, __LINE__,
223                     _("extra table_body call not allowed; there must be \
224 only one table_body after a table_begin and before a table_end."));
225   if (uiout->table.headers.size () != uiout->table.columns)
226     internal_error (__FILE__, __LINE__,
227                     _("number of headers differ from number of table \
228 columns."));
229
230   uiout->table.body_flag = 1;
231
232   uo_table_body (uiout);
233 }
234
235 static void
236 ui_out_table_end (struct ui_out *uiout)
237 {
238   if (!uiout->table.flag)
239     internal_error (__FILE__, __LINE__,
240                     _("misplaced table_end or missing table_begin."));
241
242   uiout->table.entry_level = 0;
243   uiout->table.body_flag = 0;
244   uiout->table.flag = 0;
245
246   uo_table_end (uiout);
247   clear_table (uiout);
248 }
249
250 void
251 ui_out_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
252                      const std::string &col_name, const std::string &col_hdr)
253 {
254   if (!uiout->table.flag || uiout->table.body_flag)
255     internal_error (__FILE__, __LINE__,
256                     _("table header must be specified after table_begin \
257 and before table_body."));
258
259   append_header_to_list (uiout, width, alignment, col_name, col_hdr);
260
261   uo_table_header (uiout, width, alignment, col_name, col_hdr);
262 }
263
264 static void
265 do_cleanup_table_end (void *data)
266 {
267   struct ui_out *ui_out = (struct ui_out *) data;
268
269   ui_out_table_end (ui_out);
270 }
271
272 struct cleanup *
273 make_cleanup_ui_out_table_begin_end (struct ui_out *ui_out, int nr_cols,
274                                      int nr_rows, const char *tblid)
275 {
276   ui_out_table_begin (ui_out, nr_cols, nr_rows, tblid);
277   return make_cleanup (do_cleanup_table_end, ui_out);
278 }
279
280 void
281 ui_out_begin (struct ui_out *uiout,
282               enum ui_out_type type,
283               const char *id)
284 {
285   int new_level;
286
287   if (uiout->table.flag && !uiout->table.body_flag)
288     internal_error (__FILE__, __LINE__,
289                     _("table header or table_body expected; lists must be \
290 specified after table_body."));
291
292   /* Be careful to verify the ``field'' before the new tuple/list is
293      pushed onto the stack.  That way the containing list/table/row is
294      verified and not the newly created tuple/list.  This verification
295      is needed (at least) for the case where a table row entry
296      contains either a tuple/list.  For that case bookkeeping such as
297      updating the column count or advancing to the next heading still
298      needs to be performed.  */
299   {
300     int fldno;
301     int width;
302     enum ui_align align;
303
304     verify_field (uiout, &fldno, &width, &align);
305   }
306
307   new_level = push_level (uiout, type);
308
309   /* If the push puts us at the same level as a table row entry, we've
310      got a new table row.  Put the header pointer back to the start.  */
311   if (uiout->table.body_flag
312       && uiout->table.entry_level == new_level)
313     uiout->table.headers_iterator = uiout->table.headers.begin ();
314
315   uo_begin (uiout, type, new_level, id);
316 }
317
318 void
319 ui_out_end (struct ui_out *uiout,
320             enum ui_out_type type)
321 {
322   int old_level = pop_level (uiout, type);
323
324   uo_end (uiout, type, old_level);
325 }
326
327 struct ui_out_end_cleanup_data
328 {
329   struct ui_out *uiout;
330   enum ui_out_type type;
331 };
332
333 static void
334 do_cleanup_end (void *data)
335 {
336   struct ui_out_end_cleanup_data *end_cleanup_data
337     = (struct ui_out_end_cleanup_data *) data;
338
339   ui_out_end (end_cleanup_data->uiout, end_cleanup_data->type);
340   xfree (end_cleanup_data);
341 }
342
343 static struct cleanup *
344 make_cleanup_ui_out_end (struct ui_out *uiout,
345                          enum ui_out_type type)
346 {
347   struct ui_out_end_cleanup_data *end_cleanup_data;
348
349   end_cleanup_data = XNEW (struct ui_out_end_cleanup_data);
350   end_cleanup_data->uiout = uiout;
351   end_cleanup_data->type = type;
352   return make_cleanup (do_cleanup_end, end_cleanup_data);
353 }
354
355 struct cleanup *
356 make_cleanup_ui_out_tuple_begin_end (struct ui_out *uiout,
357                                      const char *id)
358 {
359   ui_out_begin (uiout, ui_out_type_tuple, id);
360   return make_cleanup_ui_out_end (uiout, ui_out_type_tuple);
361 }
362
363 struct cleanup *
364 make_cleanup_ui_out_list_begin_end (struct ui_out *uiout,
365                                     const char *id)
366 {
367   ui_out_begin (uiout, ui_out_type_list, id);
368   return make_cleanup_ui_out_end (uiout, ui_out_type_list);
369 }
370
371 void
372 ui_out_field_int (struct ui_out *uiout,
373                   const char *fldname,
374                   int value)
375 {
376   int fldno;
377   int width;
378   enum ui_align align;
379
380   verify_field (uiout, &fldno, &width, &align);
381
382   uo_field_int (uiout, fldno, width, align, fldname, value);
383 }
384
385 void
386 ui_out_field_fmt_int (struct ui_out *uiout,
387                       int input_width,
388                       enum ui_align input_align,
389                       const char *fldname,
390                       int value)
391 {
392   int fldno;
393   int width;
394   enum ui_align align;
395
396   verify_field (uiout, &fldno, &width, &align);
397
398   uo_field_int (uiout, fldno, input_width, input_align, fldname, value);
399 }
400
401 /* Documented in ui-out.h.  */
402
403 void
404 ui_out_field_core_addr (struct ui_out *uiout,
405                         const char *fldname,
406                         struct gdbarch *gdbarch,
407                         CORE_ADDR address)
408 {
409   ui_out_field_string (uiout, fldname,
410                        print_core_address (gdbarch, address));
411 }
412
413 void
414 ui_out_field_stream (struct ui_out *uiout,
415                      const char *fldname,
416                      struct ui_file *stream)
417 {
418   std::string buffer = ui_file_as_string (stream);
419
420   if (!buffer.empty ())
421     ui_out_field_string (uiout, fldname, buffer.c_str ());
422   else
423     ui_out_field_skip (uiout, fldname);
424   ui_file_rewind (stream);
425 }
426
427 /* Used to omit a field.  */
428
429 void
430 ui_out_field_skip (struct ui_out *uiout,
431                    const char *fldname)
432 {
433   int fldno;
434   int width;
435   enum ui_align align;
436
437   verify_field (uiout, &fldno, &width, &align);
438
439   uo_field_skip (uiout, fldno, width, align, fldname);
440 }
441
442 void
443 ui_out_field_string (struct ui_out *uiout,
444                      const char *fldname,
445                      const char *string)
446 {
447   int fldno;
448   int width;
449   enum ui_align align;
450
451   verify_field (uiout, &fldno, &width, &align);
452
453   uo_field_string (uiout, fldno, width, align, fldname, string);
454 }
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   enum ui_align align;
466
467   /* Will not align, but has to call anyway.  */
468   verify_field (uiout, &fldno, &width, &align);
469
470   va_start (args, format);
471
472   uo_field_fmt (uiout, fldno, width, align, fldname, format, args);
473
474   va_end (args);
475 }
476
477 void
478 ui_out_spaces (struct ui_out *uiout, int numspaces)
479 {
480   uo_spaces (uiout, numspaces);
481 }
482
483 void
484 ui_out_text (struct ui_out *uiout,
485              const char *string)
486 {
487   uo_text (uiout, string);
488 }
489
490 void
491 ui_out_message (struct ui_out *uiout, const char *format, ...)
492 {
493   va_list args;
494
495   va_start (args, format);
496   uo_message (uiout, format, args);
497   va_end (args);
498 }
499
500 void
501 ui_out_wrap_hint (struct ui_out *uiout, const char *identstring)
502 {
503   uo_wrap_hint (uiout, identstring);
504 }
505
506 void
507 ui_out_flush (struct ui_out *uiout)
508 {
509   uo_flush (uiout);
510 }
511
512 int
513 ui_out_redirect (struct ui_out *uiout, struct ui_file *outstream)
514 {
515   return uo_redirect (uiout, outstream);
516 }
517
518 /* Test the flags against the mask given.  */
519 int
520 ui_out_test_flags (struct ui_out *uiout, int mask)
521 {
522   return (uiout->flags & mask);
523 }
524
525 int
526 ui_out_is_mi_like_p (struct ui_out *uiout)
527 {
528   return uiout->impl->is_mi_like_p;
529 }
530
531 /* Interface to the implementation functions.  */
532
533 void
534 uo_table_begin (struct ui_out *uiout, int nbrofcols,
535                 int nr_rows,
536                 const char *tblid)
537 {
538   if (!uiout->impl->table_begin)
539     return;
540   uiout->impl->table_begin (uiout, nbrofcols, nr_rows, tblid);
541 }
542
543 void
544 uo_table_body (struct ui_out *uiout)
545 {
546   if (!uiout->impl->table_body)
547     return;
548   uiout->impl->table_body (uiout);
549 }
550
551 void
552 uo_table_end (struct ui_out *uiout)
553 {
554   if (!uiout->impl->table_end)
555     return;
556   uiout->impl->table_end (uiout);
557 }
558
559 void
560 uo_table_header (struct ui_out *uiout, int width, enum ui_align align,
561                  const std::string &col_name, const std::string &col_hdr)
562 {
563   if (!uiout->impl->table_header)
564     return;
565   uiout->impl->table_header (uiout, width, align, col_name, col_hdr);
566 }
567
568 /* Clear the table associated with UIOUT.  */
569
570 static void
571 clear_table (struct ui_out *uiout)
572 {
573   uiout->table.id.clear ();
574   clear_header_list (uiout);
575 }
576
577 void
578 uo_begin (struct ui_out *uiout,
579           enum ui_out_type type,
580           int level,
581           const char *id)
582 {
583   if (uiout->impl->begin == NULL)
584     return;
585   uiout->impl->begin (uiout, type, level, id);
586 }
587
588 void
589 uo_end (struct ui_out *uiout,
590         enum ui_out_type type,
591         int level)
592 {
593   if (uiout->impl->end == NULL)
594     return;
595   uiout->impl->end (uiout, type, level);
596 }
597
598 void
599 uo_field_int (struct ui_out *uiout, int fldno, int width, enum ui_align align,
600               const char *fldname,
601               int value)
602 {
603   if (!uiout->impl->field_int)
604     return;
605   uiout->impl->field_int (uiout, fldno, width, align, fldname, value);
606 }
607
608 void
609 uo_field_skip (struct ui_out *uiout, int fldno, int width, enum ui_align align,
610                const char *fldname)
611 {
612   if (!uiout->impl->field_skip)
613     return;
614   uiout->impl->field_skip (uiout, fldno, width, align, fldname);
615 }
616
617 void
618 uo_field_string (struct ui_out *uiout, int fldno, int width,
619                  enum ui_align align,
620                  const char *fldname,
621                  const char *string)
622 {
623   if (!uiout->impl->field_string)
624     return;
625   uiout->impl->field_string (uiout, fldno, width, align, fldname, string);
626 }
627
628 void
629 uo_field_fmt (struct ui_out *uiout, int fldno, int width, enum ui_align align,
630               const char *fldname,
631               const char *format,
632               va_list args)
633 {
634   if (!uiout->impl->field_fmt)
635     return;
636   uiout->impl->field_fmt (uiout, fldno, width, align, fldname, format, args);
637 }
638
639 void
640 uo_spaces (struct ui_out *uiout, int numspaces)
641 {
642   if (!uiout->impl->spaces)
643     return;
644   uiout->impl->spaces (uiout, numspaces);
645 }
646
647 void
648 uo_text (struct ui_out *uiout,
649          const char *string)
650 {
651   if (!uiout->impl->text)
652     return;
653   uiout->impl->text (uiout, string);
654 }
655
656 void
657 uo_message (struct ui_out *uiout,
658             const char *format,
659             va_list args)
660 {
661   if (!uiout->impl->message)
662     return;
663   uiout->impl->message (uiout, format, args);
664 }
665
666 void
667 uo_wrap_hint (struct ui_out *uiout, const char *identstring)
668 {
669   if (!uiout->impl->wrap_hint)
670     return;
671   uiout->impl->wrap_hint (uiout, identstring);
672 }
673
674 void
675 uo_flush (struct ui_out *uiout)
676 {
677   if (!uiout->impl->flush)
678     return;
679   uiout->impl->flush (uiout);
680 }
681
682 int
683 uo_redirect (struct ui_out *uiout, struct ui_file *outstream)
684 {
685   if (!uiout->impl->redirect)
686     return -1;
687   return uiout->impl->redirect (uiout, outstream);
688 }
689
690 /* local functions */
691
692 /* List of column headers manipulation routines.  */
693
694 static void
695 clear_header_list (struct ui_out *uiout)
696 {
697   uiout->table.headers.clear ();
698   uiout->table.headers_iterator = uiout->table.headers.end ();
699 }
700
701 static void
702 append_header_to_list (struct ui_out *uiout,
703                        int width,
704                        enum ui_align alignment,
705                        const std::string &col_name,
706                        const std::string &col_hdr)
707 {
708   std::unique_ptr<ui_out_hdr> temphdr (new ui_out_hdr ());
709
710   temphdr->width = width;
711   temphdr->alignment = alignment;
712
713   /* Make our own copy of the strings, since the lifetime of the original
714      versions may be too short.  */
715   temphdr->col_hdr = col_hdr;
716   temphdr->col_name = col_name;
717
718   temphdr->colno = uiout->table.headers.size () + 1;
719
720   uiout->table.headers.push_back (std::move (temphdr));
721 }
722
723 /* Extract the format information for the NEXT header and advance
724    the header pointer.  Return 0 if there was no next header.  */
725
726 static int
727 get_next_header (struct ui_out *uiout,
728                  int *colno,
729                  int *width,
730                  enum ui_align *alignment,
731                  const char **col_hdr)
732 {
733   /* There may be no headers at all or we may have used all columns.  */
734   if (uiout->table.headers_iterator == uiout->table.headers.end ())
735     return 0;
736
737   ui_out_hdr *hdr = uiout->table.headers_iterator->get ();
738
739   *colno = hdr->colno;
740   *width = hdr->width;
741   *alignment = hdr->alignment;
742   *col_hdr = hdr->col_hdr.c_str ();
743
744   /* Advance the header pointer to the next entry.  */
745   uiout->table.headers_iterator++;
746
747   return 1;
748 }
749
750
751 /* Verify that the field/tuple/list is correctly positioned.  Return
752    the field number and corresponding alignment (if
753    available/applicable).  */
754
755 static void
756 verify_field (struct ui_out *uiout, int *fldno, int *width,
757               enum ui_align *align)
758 {
759   struct ui_out_level *current = current_level (uiout);
760   const char *text;
761
762   if (uiout->table.flag)
763     {
764       if (!uiout->table.body_flag)
765         internal_error (__FILE__, __LINE__,
766                         _("table_body missing; table fields must be \
767 specified after table_body and inside a list."));
768       /* NOTE: cagney/2001-12-08: There was a check here to ensure
769          that this code was only executed when uiout->level was
770          greater than zero.  That no longer applies - this code is run
771          before each table row tuple is started and at that point the
772          level is zero.  */
773     }
774
775   current->field_count += 1;
776
777   if (uiout->table.body_flag
778       && uiout->table.entry_level == uiout->level
779       && get_next_header (uiout, fldno, width, align, &text))
780     {
781       if (*fldno != current->field_count)
782         internal_error (__FILE__, __LINE__,
783                         _("ui-out internal error in handling headers."));
784     }
785   else
786     {
787       *width = 0;
788       *align = ui_noalign;
789       *fldno = current->field_count;
790     }
791 }
792
793
794 /* Access to ui-out members data.  */
795
796 void *
797 ui_out_data (struct ui_out *uiout)
798 {
799   return uiout->data;
800 }
801
802 /* Access table field parameters.  */
803 int
804 ui_out_query_field (struct ui_out *uiout, int colno,
805                     int *width, int *alignment, const char **col_name)
806 {
807   if (!uiout->table.flag)
808     return 0;
809
810   /* Column numbers are 1-based, so convert to 0-based index.  */
811   int index = colno - 1;
812
813   if (index >= 0 && index < uiout->table.headers.size ())
814     {
815       ui_out_hdr *hdr = uiout->table.headers[index].get ();
816
817       gdb_assert (colno == hdr->colno);
818
819       *width = hdr->width;
820       *alignment = hdr->alignment;
821       *col_name = hdr->col_name.c_str ();
822
823       return 1;
824     }
825   else
826     return 0;
827 }
828
829 /* Initialize private members at startup.  */
830
831 struct ui_out *
832 ui_out_new (const struct ui_out_impl *impl, void *data,
833             int flags)
834 {
835   struct ui_out *uiout = new ui_out ();
836   std::unique_ptr<ui_out_level> current (new ui_out_level ());
837
838   uiout->data = data;
839   uiout->impl = impl;
840   uiout->flags = flags;
841   uiout->table.flag = 0;
842   uiout->table.body_flag = 0;
843   uiout->level = 0;
844
845   /* Create uiout->level 0, the default level.  */
846   current->type = ui_out_type_tuple;
847   current->field_count = 0;
848   uiout->levels.push_back (std::move (current));
849
850   uiout->table.headers_iterator = uiout->table.headers.end ();
851
852   return uiout;
853 }