1 /* Python implementation of ui_out
2 
3    Copyright (C) 2023-2024 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #ifndef GDB_PYTHON_PY_UIOUT_H
21 #define GDB_PYTHON_PY_UIOUT_H
22 
23 #include "python-internal.h"
24 #include "ui-out.h"
25 
26 /* A ui_out subclass that creates a Python object based on the data
27    that is passed in.  */
28 
29 class py_ui_out : public ui_out
30 {
31 public:
32 
py_ui_out()33   py_ui_out ()
34     : ui_out (fix_multi_location_breakpoint_output
35                 | fix_breakpoint_script_output)
36   {
37     do_begin (ui_out_type_tuple, nullptr);
38   }
39 
can_emit_style_escape()40   bool can_emit_style_escape () const override
41   { return false; }
42 
do_is_mi_like_p()43   bool do_is_mi_like_p () const override
44   { return true; }
45 
46   /* Return the Python object that was created.  If a Python error
47      occurred during the processing, set the Python error and return
48      nullptr.  */
result()49   gdbpy_ref<> result ()
50   {
51     if (m_error.has_value ())
52       {
53           m_error->restore ();
54           return nullptr;
55       }
56     return std::move (current ().obj);
57   }
58 
current_stream()59   ui_file *current_stream () const override
60   { return nullptr; }
61 
62 protected:
63 
do_progress_end()64   void do_progress_end () override { }
do_progress_start()65   void do_progress_start () override { }
do_progress_notify(const std::string &,const char *,double,double)66   void do_progress_notify (const std::string &, const char *, double, double)
67     override
68   { }
69 
do_table_begin(int nbrofcols,int nr_rows,const char * tblid)70   void do_table_begin (int nbrofcols, int nr_rows, const char *tblid) override
71   {
72     do_begin (ui_out_type_list, tblid);
73   }
do_table_body()74   void do_table_body () override
75   { }
do_table_end()76   void do_table_end () override
77   {
78     do_end (ui_out_type_list);
79   }
do_table_header(int width,ui_align align,const std::string & col_name,const std::string & col_hdr)80   void do_table_header (int width, ui_align align,
81                               const std::string &col_name,
82                               const std::string &col_hdr) override
83   { }
84 
85   void do_begin (ui_out_type type, const char *id) override;
86   void do_end (ui_out_type type) override;
87 
88   void do_field_signed (int fldno, int width, ui_align align,
89                               const char *fldname, LONGEST value) override;
90   void do_field_unsigned (int fldno, int width, ui_align align,
91                                 const char *fldname, ULONGEST value) override;
92 
do_field_skip(int fldno,int width,ui_align align,const char * fldname)93   void do_field_skip (int fldno, int width, ui_align align,
94                           const char *fldname) override
95   { }
96 
97   void do_field_string (int fldno, int width, ui_align align,
98                               const char *fldname, const char *string,
99                               const ui_file_style &style) override;
100   void do_field_fmt (int fldno, int width, ui_align align,
101                          const char *fldname, const ui_file_style &style,
102                          const char *format, va_list args) override
103     ATTRIBUTE_PRINTF (7, 0);
104 
do_spaces(int numspaces)105   void do_spaces (int numspaces) override
106   { }
107 
do_text(const char * string)108   void do_text (const char *string) override
109   { }
110 
do_message(const ui_file_style & style,const char * format,va_list args)111   void do_message (const ui_file_style &style,
112                        const char *format, va_list args)
113     override ATTRIBUTE_PRINTF (3,0)
114   { }
115 
do_wrap_hint(int indent)116   void do_wrap_hint (int indent) override
117   { }
118 
do_flush()119   void do_flush () override
120   { }
121 
do_redirect(struct ui_file * outstream)122   void do_redirect (struct ui_file *outstream) override
123   { }
124 
125 private:
126 
127   /* When constructing Python objects, this class keeps a stack of
128      objects being constructed.  Each such object has this type.  */
129   struct object_desc
130   {
131     /* Name of the field (or empty for lists) that this object will
132        eventually become.  */
133     std::string field_name;
134     /* The object under construction.  */
135     gdbpy_ref<> obj;
136     /* The type of structure being created.  Note that tables are
137        treated as lists here.  */
138     ui_out_type type;
139   };
140 
141   /* The stack of objects being created.  */
142   std::vector<object_desc> m_objects;
143 
144   /* If an error occurred, this holds the exception information for
145      use by the 'release' method.  */
146   std::optional<gdbpy_err_fetch> m_error;
147 
148   /* Return a reference to the object under construction.  */
current()149   object_desc &current ()
150   { return m_objects.back (); }
151 
152   /* Add a new field to the current object under construction.  */
153   void add_field (const char *name, const gdbpy_ref<> &obj);
154 };
155 
156 #endif /* GDB_PYTHON_PY_UIOUT_H */
157