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