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