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