| /* Output generating routines for GDB. | 
 |  | 
 |    Copyright (C) 1999-2022 Free Software Foundation, Inc. | 
 |  | 
 |    Contributed by Cygnus Solutions. | 
 |    Written by Fernando Nasser for Cygnus. | 
 |  | 
 |    This file is part of GDB. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #ifndef UI_OUT_H | 
 | #define UI_OUT_H 1 | 
 |  | 
 | #include <vector> | 
 |  | 
 | #include "gdbsupport/enum-flags.h" | 
 | #include "ui-style.h" | 
 |  | 
 | class ui_out_level; | 
 | class ui_out_table; | 
 | struct ui_file; | 
 |  | 
 | /* the current ui_out */ | 
 |  | 
 | /* FIXME: This should not be a global but something passed down from main.c | 
 |    or top.c.  */ | 
 | extern struct ui_out **current_ui_current_uiout_ptr (void); | 
 | #define current_uiout (*current_ui_current_uiout_ptr ()) | 
 |  | 
 | /* alignment enum */ | 
 | enum ui_align | 
 |   { | 
 |     ui_left = -1, | 
 |     ui_center, | 
 |     ui_right, | 
 |     ui_noalign | 
 |   }; | 
 |  | 
 | /* flags enum */ | 
 | enum ui_out_flag | 
 | { | 
 |   ui_source_list = (1 << 0), | 
 |   fix_multi_location_breakpoint_output = (1 << 1), | 
 |   /* This indicates that %pF should be disallowed in a printf format | 
 |      string.  */ | 
 |   disallow_ui_out_field = (1 << 2) | 
 | }; | 
 |  | 
 | DEF_ENUM_FLAGS_TYPE (ui_out_flag, ui_out_flags); | 
 |  | 
 | /* Prototypes for ui-out API.  */ | 
 |  | 
 | /* A result is a recursive data structure consisting of lists and | 
 |    tuples.  */ | 
 |  | 
 | enum ui_out_type | 
 |   { | 
 |     ui_out_type_tuple, | 
 |     ui_out_type_list | 
 |   }; | 
 |  | 
 | /* The possible kinds of fields.  */ | 
 | enum class field_kind | 
 |   { | 
 |     /* "FIELD_STRING" needs a funny name to avoid clashes with tokens | 
 |        named "STRING".  See PR build/25250.  FIELD_SIGNED is given a | 
 |        similar name for consistency.  */ | 
 |     FIELD_SIGNED, | 
 |     FIELD_STRING, | 
 |   }; | 
 |  | 
 | /* The base type of all fields that can be emitted using %pF.  */ | 
 |  | 
 | struct base_field_s | 
 | { | 
 |   const char *name; | 
 |   field_kind kind; | 
 | }; | 
 |  | 
 | /* A signed integer field, to be passed to %pF in format strings.  */ | 
 |  | 
 | struct signed_field_s : base_field_s | 
 | { | 
 |   LONGEST val; | 
 | }; | 
 |  | 
 | /* Construct a temporary signed_field_s on the caller's stack and | 
 |    return a pointer to the constructed object.  We use this because | 
 |    it's not possible to pass a reference via va_args.  */ | 
 |  | 
 | static inline signed_field_s * | 
 | signed_field (const char *name, LONGEST val, | 
 | 	      signed_field_s &&tmp = {}) | 
 | { | 
 |   tmp.name = name; | 
 |   tmp.kind = field_kind::FIELD_SIGNED; | 
 |   tmp.val = val; | 
 |   return &tmp; | 
 | } | 
 |  | 
 | /* A string field, to be passed to %pF in format strings.  */ | 
 |  | 
 | struct string_field_s : base_field_s | 
 | { | 
 |   const char *str; | 
 | }; | 
 |  | 
 | /* Construct a temporary string_field_s on the caller's stack and | 
 |    return a pointer to the constructed object.  We use this because | 
 |    it's not possible to pass a reference via va_args.  */ | 
 |  | 
 | static inline string_field_s * | 
 | string_field (const char *name, const char *str, | 
 | 	      string_field_s &&tmp = {}) | 
 | { | 
 |   tmp.name = name; | 
 |   tmp.kind = field_kind::FIELD_STRING; | 
 |   tmp.str = str; | 
 |   return &tmp; | 
 | } | 
 |  | 
 | /* A styled string.  */ | 
 |  | 
 | struct styled_string_s | 
 | { | 
 |   /* The style.  */ | 
 |   ui_file_style style; | 
 |  | 
 |   /* The string.  */ | 
 |   const char *str; | 
 | }; | 
 |  | 
 | /* Construct a temporary styled_string_s on the caller's stack and | 
 |    return a pointer to the constructed object.  We use this because | 
 |    it's not possible to pass a reference via va_args.  */ | 
 |  | 
 | static inline styled_string_s * | 
 | styled_string (const ui_file_style &style, const char *str, | 
 | 	       styled_string_s &&tmp = {}) | 
 | { | 
 |   tmp.style = style; | 
 |   tmp.str = str; | 
 |   return &tmp; | 
 | } | 
 |  | 
 | class ui_out | 
 | { | 
 |  public: | 
 |  | 
 |   explicit ui_out (ui_out_flags flags = 0); | 
 |   virtual ~ui_out (); | 
 |  | 
 |   void push_level (ui_out_type type); | 
 |   void pop_level (ui_out_type type); | 
 |  | 
 |   /* A table can be considered a special tuple/list combination with the | 
 |      implied structure: ``table = { hdr = { header, ... } , body = [ { | 
 |      field, ... }, ... ] }''.  If NR_ROWS is negative then there is at | 
 |      least one row.  */ | 
 |  | 
 |   void table_begin (int nr_cols, int nr_rows, const std::string &tblid); | 
 |   void table_header (int width, ui_align align, const std::string &col_name, | 
 | 		     const std::string &col_hdr); | 
 |   void table_body (); | 
 |   void table_end (); | 
 |  | 
 |   void begin (ui_out_type type, const char *id); | 
 |   void end (ui_out_type type); | 
 |  | 
 |   void field_signed (const char *fldname, LONGEST value); | 
 |   void field_fmt_signed (int width, ui_align align, const char *fldname, | 
 | 			 LONGEST value); | 
 |   /* Like field_signed, but print an unsigned value.  */ | 
 |   void field_unsigned (const char *fldname, ULONGEST value); | 
 |   void field_core_addr (const char *fldname, struct gdbarch *gdbarch, | 
 | 			CORE_ADDR address); | 
 |   void field_string (const char *fldname, const char *string, | 
 | 		     const ui_file_style &style = ui_file_style ()); | 
 |   void field_string (const char *fldname, const std::string &string, | 
 | 		     const ui_file_style &style = ui_file_style ()) | 
 |   { | 
 |     field_string (fldname, string.c_str (), style); | 
 |   } | 
 |   void field_stream (const char *fldname, string_file &stream, | 
 | 		     const ui_file_style &style = ui_file_style ()); | 
 |   void field_skip (const char *fldname); | 
 |   void field_fmt (const char *fldname, const char *format, ...) | 
 |     ATTRIBUTE_PRINTF (3, 4); | 
 |   void field_fmt (const char *fldname, const ui_file_style &style, | 
 | 		  const char *format, ...) | 
 |     ATTRIBUTE_PRINTF (4, 5); | 
 |  | 
 |   void spaces (int numspaces); | 
 |   void text (const char *string); | 
 |   void text (const std::string &string) { text (string.c_str ()); } | 
 |  | 
 |   /* Output a printf-style formatted string.  In addition to the usual | 
 |      printf format specs, this supports a few GDB-specific | 
 |      formatters: | 
 |  | 
 |      - '%pF' - output a field. | 
 |  | 
 |        The argument is a field, wrapped in any of the base_field_s | 
 |        subclasses.  signed_field for integer fields, string_field for | 
 |        string fields.  This is preferred over separate | 
 |        uiout->field_signed(), uiout_>field_string() etc. calls when | 
 |        the formatted message is translatable.  E.g.: | 
 |  | 
 | 	 uiout->message (_("\nWatchpoint %pF deleted because the program has " | 
 | 			 "left the block in\n" | 
 | 			 "which its expression is valid.\n"), | 
 | 			 signed_field ("wpnum", b->number)); | 
 |  | 
 |      - '%p[' - output the following text in a specified style. | 
 |        '%p]' - output the following text in the default style. | 
 |  | 
 |        The argument to '%p[' is a ui_file_style pointer.  The argument | 
 |        to '%p]' must be nullptr. | 
 |  | 
 |        This is useful when you want to output some portion of a string | 
 |        literal in some style.  E.g.: | 
 |  | 
 | 	 uiout->message (_(" %p[<repeats %u times>%p]"), | 
 | 			 metadata_style.style ().ptr (), | 
 | 			 reps, repeats, nullptr); | 
 |  | 
 |      - '%ps' - output a styled string. | 
 |  | 
 |        The argument is the result of a call to styled_string.  This is | 
 |        useful when you want to output some runtime-generated string in | 
 |        some style.  E.g.: | 
 |  | 
 | 	 uiout->message (_("this is a target address %ps.\n"), | 
 | 			 styled_string (address_style.style (), | 
 | 					paddress (gdbarch, pc))); | 
 |  | 
 |      Note that these all "abuse" the %p printf format spec, in order | 
 |      to be compatible with GCC's printf format checking.  This is OK | 
 |      because code in GDB that wants to print a host address should use | 
 |      host_address_to_string instead of %p.  */ | 
 |   void message (const char *format, ...) ATTRIBUTE_PRINTF (2, 3); | 
 |   void vmessage (const ui_file_style &in_style, | 
 | 		 const char *format, va_list args) ATTRIBUTE_PRINTF (3, 0); | 
 |  | 
 |   void wrap_hint (int indent); | 
 |  | 
 |   void flush (); | 
 |  | 
 |   /* Redirect the output of a ui_out object temporarily.  */ | 
 |   void redirect (ui_file *outstream); | 
 |  | 
 |   ui_out_flags test_flags (ui_out_flags mask); | 
 |  | 
 |   /* HACK: Code in GDB is currently checking to see the type of ui_out | 
 |      builder when determining which output to produce.  This function is | 
 |      a hack to encapsulate that test.  Once GDB manages to separate the | 
 |      CLI/MI from the core of GDB the problem should just go away ....  */ | 
 |  | 
 |   bool is_mi_like_p () const; | 
 |  | 
 |   bool query_table_field (int colno, int *width, int *alignment, | 
 | 			  const char **col_name); | 
 |  | 
 |   /* Return true if this stream is prepared to handle style | 
 |      escapes.  */ | 
 |   virtual bool can_emit_style_escape () const = 0; | 
 |  | 
 |   /* An object that starts and finishes a progress meter.  */ | 
 |   class progress_meter | 
 |   { | 
 |   public: | 
 |     /* SHOULD_PRINT indicates whether something should be printed for a tty.  */ | 
 |     progress_meter (struct ui_out *uiout, const std::string &name, | 
 | 		    bool should_print) | 
 |       : m_uiout (uiout) | 
 |     { | 
 |       m_uiout->do_progress_start (name, should_print); | 
 |     } | 
 |  | 
 |     ~progress_meter () | 
 |     { | 
 |       m_uiout->do_progress_notify (1.0); | 
 |       m_uiout->do_progress_end (); | 
 |     } | 
 |  | 
 |     progress_meter (const progress_meter &) = delete; | 
 |     progress_meter &operator= (const progress_meter &) = delete; | 
 |  | 
 |     /* Emit some progress for this progress meter.  HOWMUCH may range | 
 |        from 0.0 to 1.0.  */ | 
 |     void progress (double howmuch) | 
 |     { | 
 |       m_uiout->do_progress_notify (howmuch); | 
 |     } | 
 |  | 
 |   private: | 
 |  | 
 |     struct ui_out *m_uiout; | 
 |   }; | 
 |  | 
 |  protected: | 
 |  | 
 |   virtual void do_table_begin (int nbrofcols, int nr_rows, const char *tblid) | 
 |     = 0; | 
 |   virtual void do_table_body () = 0; | 
 |   virtual void do_table_end () = 0; | 
 |   virtual void do_table_header (int width, ui_align align, | 
 | 				const std::string &col_name, | 
 | 				const std::string &col_hdr) = 0; | 
 |  | 
 |   virtual void do_begin (ui_out_type type, const char *id) = 0; | 
 |   virtual void do_end (ui_out_type type) = 0; | 
 |   virtual void do_field_signed (int fldno, int width, ui_align align, | 
 | 				const char *fldname, LONGEST value) = 0; | 
 |   virtual void do_field_unsigned (int fldno, int width, ui_align align, | 
 | 				  const char *fldname, ULONGEST value) = 0; | 
 |   virtual void do_field_skip (int fldno, int width, ui_align align, | 
 | 			      const char *fldname) = 0; | 
 |   virtual void do_field_string (int fldno, int width, ui_align align, | 
 | 				const char *fldname, const char *string, | 
 | 				const ui_file_style &style) = 0; | 
 |   virtual void do_field_fmt (int fldno, int width, ui_align align, | 
 | 			     const char *fldname, const ui_file_style &style, | 
 | 			     const char *format, va_list args) | 
 |     ATTRIBUTE_PRINTF (7, 0) = 0; | 
 |   virtual void do_spaces (int numspaces) = 0; | 
 |   virtual void do_text (const char *string) = 0; | 
 |   virtual void do_message (const ui_file_style &style, | 
 | 			   const char *format, va_list args) | 
 |     ATTRIBUTE_PRINTF (3,0) = 0; | 
 |   virtual void do_wrap_hint (int indent) = 0; | 
 |   virtual void do_flush () = 0; | 
 |   virtual void do_redirect (struct ui_file *outstream) = 0; | 
 |  | 
 |   virtual void do_progress_start (const std::string &, bool) = 0; | 
 |   virtual void do_progress_notify (double) = 0; | 
 |   virtual void do_progress_end () = 0; | 
 |  | 
 |   /* Set as not MI-like by default.  It is overridden in subclasses if | 
 |      necessary.  */ | 
 |  | 
 |   virtual bool do_is_mi_like_p () const | 
 |   { return false; } | 
 |  | 
 |  private: | 
 |   void call_do_message (const ui_file_style &style, const char *format, | 
 | 			...); | 
 |  | 
 |   ui_out_flags m_flags; | 
 |  | 
 |   /* Vector to store and track the ui-out levels.  */ | 
 |   std::vector<std::unique_ptr<ui_out_level>> m_levels; | 
 |  | 
 |   /* A table, if any.  At present only a single table is supported.  */ | 
 |   std::unique_ptr<ui_out_table> m_table_up; | 
 |  | 
 |   void verify_field (int *fldno, int *width, ui_align *align); | 
 |  | 
 |   int level () const; | 
 |   ui_out_level *current_level () const; | 
 | }; | 
 |  | 
 | /* Start a new tuple or list on construction, and end it on | 
 |    destruction.  Normally this is used via the typedefs | 
 |    ui_out_emit_tuple and ui_out_emit_list.  */ | 
 | template<ui_out_type Type> | 
 | class ui_out_emit_type | 
 | { | 
 | public: | 
 |  | 
 |   ui_out_emit_type (struct ui_out *uiout, const char *id) | 
 |     : m_uiout (uiout) | 
 |   { | 
 |     uiout->begin (Type, id); | 
 |   } | 
 |  | 
 |   ~ui_out_emit_type () | 
 |   { | 
 |     m_uiout->end (Type); | 
 |   } | 
 |  | 
 |   DISABLE_COPY_AND_ASSIGN (ui_out_emit_type<Type>); | 
 |  | 
 | private: | 
 |  | 
 |   struct ui_out *m_uiout; | 
 | }; | 
 |  | 
 | typedef ui_out_emit_type<ui_out_type_tuple> ui_out_emit_tuple; | 
 | typedef ui_out_emit_type<ui_out_type_list> ui_out_emit_list; | 
 |  | 
 | /* Start a new table on construction, and end the table on | 
 |    destruction.  */ | 
 | class ui_out_emit_table | 
 | { | 
 | public: | 
 |  | 
 |   ui_out_emit_table (struct ui_out *uiout, int nr_cols, int nr_rows, | 
 | 		     const char *tblid) | 
 |     : m_uiout (uiout) | 
 |   { | 
 |     m_uiout->table_begin (nr_cols, nr_rows, tblid); | 
 |   } | 
 |  | 
 |   ~ui_out_emit_table () | 
 |   { | 
 |     m_uiout->table_end (); | 
 |   } | 
 |  | 
 |   ui_out_emit_table (const ui_out_emit_table &) = delete; | 
 |   ui_out_emit_table &operator= (const ui_out_emit_table &) = delete; | 
 |  | 
 | private: | 
 |  | 
 |   struct ui_out *m_uiout; | 
 | }; | 
 |  | 
 | /* On destruction, pop the last redirection by calling the uiout's | 
 |    redirect method with a NULL parameter.  */ | 
 | class ui_out_redirect_pop | 
 | { | 
 | public: | 
 |  | 
 |   ui_out_redirect_pop (ui_out *uiout) | 
 |     : m_uiout (uiout) | 
 |   { | 
 |   } | 
 |  | 
 |   ~ui_out_redirect_pop () | 
 |   { | 
 |     m_uiout->redirect (NULL); | 
 |   } | 
 |  | 
 |   ui_out_redirect_pop (const ui_out_redirect_pop &) = delete; | 
 |   ui_out_redirect_pop &operator= (const ui_out_redirect_pop &) = delete; | 
 |  | 
 | private: | 
 |   struct ui_out *m_uiout; | 
 | }; | 
 |  | 
 | #endif /* UI_OUT_H */ |