GDB (API)
|
00001 /* Output generating routines for GDB CLI. 00002 00003 Copyright (C) 1999-2013 Free Software Foundation, Inc. 00004 00005 Contributed by Cygnus Solutions. 00006 Written by Fernando Nasser for Cygnus. 00007 00008 This file is part of GDB. 00009 00010 This program is free software; you can redistribute it and/or modify 00011 it under the terms of the GNU General Public License as published by 00012 the Free Software Foundation; either version 3 of the License, or 00013 (at your option) any later version. 00014 00015 This program is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00022 00023 #include "defs.h" 00024 #include "ui-out.h" 00025 #include "cli-out.h" 00026 #include "gdb_string.h" 00027 #include "gdb_assert.h" 00028 #include "vec.h" 00029 00030 typedef struct cli_ui_out_data cli_out_data; 00031 00032 00033 /* Prototypes for local functions */ 00034 00035 static void cli_text (struct ui_out *uiout, const char *string); 00036 00037 static void field_separator (void); 00038 00039 static void out_field_fmt (struct ui_out *uiout, int fldno, 00040 const char *fldname, 00041 const char *format,...) ATTRIBUTE_PRINTF (4, 5); 00042 00043 /* These are the CLI output functions */ 00044 00045 /* Mark beginning of a table */ 00046 00047 static void 00048 cli_table_begin (struct ui_out *uiout, int nbrofcols, 00049 int nr_rows, 00050 const char *tblid) 00051 { 00052 cli_out_data *data = ui_out_data (uiout); 00053 00054 if (nr_rows == 0) 00055 data->suppress_output = 1; 00056 else 00057 /* Only the table suppresses the output and, fortunately, a table 00058 is not a recursive data structure. */ 00059 gdb_assert (data->suppress_output == 0); 00060 } 00061 00062 /* Mark beginning of a table body */ 00063 00064 static void 00065 cli_table_body (struct ui_out *uiout) 00066 { 00067 cli_out_data *data = ui_out_data (uiout); 00068 00069 if (data->suppress_output) 00070 return; 00071 /* first, close the table header line */ 00072 cli_text (uiout, "\n"); 00073 } 00074 00075 /* Mark end of a table */ 00076 00077 static void 00078 cli_table_end (struct ui_out *uiout) 00079 { 00080 cli_out_data *data = ui_out_data (uiout); 00081 00082 data->suppress_output = 0; 00083 } 00084 00085 /* Specify table header */ 00086 00087 static void 00088 cli_table_header (struct ui_out *uiout, int width, enum ui_align alignment, 00089 const char *col_name, 00090 const char *colhdr) 00091 { 00092 cli_out_data *data = ui_out_data (uiout); 00093 00094 if (data->suppress_output) 00095 return; 00096 00097 /* Always go through the function pointer (virtual function call). 00098 We may have been extended. */ 00099 uo_field_string (uiout, 0, width, alignment, 0, colhdr); 00100 } 00101 00102 /* Mark beginning of a list */ 00103 00104 static void 00105 cli_begin (struct ui_out *uiout, 00106 enum ui_out_type type, 00107 int level, 00108 const char *id) 00109 { 00110 cli_out_data *data = ui_out_data (uiout); 00111 00112 if (data->suppress_output) 00113 return; 00114 } 00115 00116 /* Mark end of a list */ 00117 00118 static void 00119 cli_end (struct ui_out *uiout, 00120 enum ui_out_type type, 00121 int level) 00122 { 00123 cli_out_data *data = ui_out_data (uiout); 00124 00125 if (data->suppress_output) 00126 return; 00127 } 00128 00129 /* output an int field */ 00130 00131 static void 00132 cli_field_int (struct ui_out *uiout, int fldno, int width, 00133 enum ui_align alignment, 00134 const char *fldname, int value) 00135 { 00136 char buffer[20]; /* FIXME: how many chars long a %d can become? */ 00137 cli_out_data *data = ui_out_data (uiout); 00138 00139 if (data->suppress_output) 00140 return; 00141 xsnprintf (buffer, sizeof (buffer), "%d", value); 00142 00143 /* Always go through the function pointer (virtual function call). 00144 We may have been extended. */ 00145 uo_field_string (uiout, fldno, width, alignment, fldname, buffer); 00146 } 00147 00148 /* used to ommit a field */ 00149 00150 static void 00151 cli_field_skip (struct ui_out *uiout, int fldno, int width, 00152 enum ui_align alignment, 00153 const char *fldname) 00154 { 00155 cli_out_data *data = ui_out_data (uiout); 00156 00157 if (data->suppress_output) 00158 return; 00159 00160 /* Always go through the function pointer (virtual function call). 00161 We may have been extended. */ 00162 uo_field_string (uiout, fldno, width, alignment, fldname, ""); 00163 } 00164 00165 /* other specific cli_field_* end up here so alignment and field 00166 separators are both handled by cli_field_string */ 00167 00168 static void 00169 cli_field_string (struct ui_out *uiout, 00170 int fldno, 00171 int width, 00172 enum ui_align align, 00173 const char *fldname, 00174 const char *string) 00175 { 00176 int before = 0; 00177 int after = 0; 00178 cli_out_data *data = ui_out_data (uiout); 00179 00180 if (data->suppress_output) 00181 return; 00182 00183 if ((align != ui_noalign) && string) 00184 { 00185 before = width - strlen (string); 00186 if (before <= 0) 00187 before = 0; 00188 else 00189 { 00190 if (align == ui_right) 00191 after = 0; 00192 else if (align == ui_left) 00193 { 00194 after = before; 00195 before = 0; 00196 } 00197 else 00198 /* ui_center */ 00199 { 00200 after = before / 2; 00201 before -= after; 00202 } 00203 } 00204 } 00205 00206 if (before) 00207 ui_out_spaces (uiout, before); 00208 if (string) 00209 out_field_fmt (uiout, fldno, fldname, "%s", string); 00210 if (after) 00211 ui_out_spaces (uiout, after); 00212 00213 if (align != ui_noalign) 00214 field_separator (); 00215 } 00216 00217 /* This is the only field function that does not align. */ 00218 00219 static void ATTRIBUTE_PRINTF (6, 0) 00220 cli_field_fmt (struct ui_out *uiout, int fldno, 00221 int width, enum ui_align align, 00222 const char *fldname, 00223 const char *format, 00224 va_list args) 00225 { 00226 cli_out_data *data = ui_out_data (uiout); 00227 struct ui_file *stream; 00228 00229 if (data->suppress_output) 00230 return; 00231 00232 stream = VEC_last (ui_filep, data->streams); 00233 vfprintf_filtered (stream, format, args); 00234 00235 if (align != ui_noalign) 00236 field_separator (); 00237 } 00238 00239 static void 00240 cli_spaces (struct ui_out *uiout, int numspaces) 00241 { 00242 cli_out_data *data = ui_out_data (uiout); 00243 struct ui_file *stream; 00244 00245 if (data->suppress_output) 00246 return; 00247 00248 stream = VEC_last (ui_filep, data->streams); 00249 print_spaces_filtered (numspaces, stream); 00250 } 00251 00252 static void 00253 cli_text (struct ui_out *uiout, const char *string) 00254 { 00255 cli_out_data *data = ui_out_data (uiout); 00256 struct ui_file *stream; 00257 00258 if (data->suppress_output) 00259 return; 00260 00261 stream = VEC_last (ui_filep, data->streams); 00262 fputs_filtered (string, stream); 00263 } 00264 00265 static void ATTRIBUTE_PRINTF (3, 0) 00266 cli_message (struct ui_out *uiout, int verbosity, 00267 const char *format, va_list args) 00268 { 00269 cli_out_data *data = ui_out_data (uiout); 00270 00271 if (data->suppress_output) 00272 return; 00273 00274 if (ui_out_get_verblvl (uiout) >= verbosity) 00275 { 00276 struct ui_file *stream = VEC_last (ui_filep, data->streams); 00277 00278 vfprintf_unfiltered (stream, format, args); 00279 } 00280 } 00281 00282 static void 00283 cli_wrap_hint (struct ui_out *uiout, char *identstring) 00284 { 00285 cli_out_data *data = ui_out_data (uiout); 00286 00287 if (data->suppress_output) 00288 return; 00289 wrap_here (identstring); 00290 } 00291 00292 static void 00293 cli_flush (struct ui_out *uiout) 00294 { 00295 cli_out_data *data = ui_out_data (uiout); 00296 struct ui_file *stream = VEC_last (ui_filep, data->streams); 00297 00298 gdb_flush (stream); 00299 } 00300 00301 /* OUTSTREAM as non-NULL will push OUTSTREAM on the stack of output streams 00302 and make it therefore active. OUTSTREAM as NULL will pop the last pushed 00303 output stream; it is an internal error if it does not exist. */ 00304 00305 static int 00306 cli_redirect (struct ui_out *uiout, struct ui_file *outstream) 00307 { 00308 cli_out_data *data = ui_out_data (uiout); 00309 00310 if (outstream != NULL) 00311 VEC_safe_push (ui_filep, data->streams, outstream); 00312 else 00313 VEC_pop (ui_filep, data->streams); 00314 00315 return 0; 00316 } 00317 00318 /* local functions */ 00319 00320 /* Like cli_field_fmt, but takes a variable number of args 00321 and makes a va_list and does not insert a separator. */ 00322 00323 /* VARARGS */ 00324 static void 00325 out_field_fmt (struct ui_out *uiout, int fldno, 00326 const char *fldname, 00327 const char *format,...) 00328 { 00329 cli_out_data *data = ui_out_data (uiout); 00330 struct ui_file *stream = VEC_last (ui_filep, data->streams); 00331 va_list args; 00332 00333 va_start (args, format); 00334 vfprintf_filtered (stream, format, args); 00335 00336 va_end (args); 00337 } 00338 00339 /* Access to ui_out format private members. */ 00340 00341 static void 00342 field_separator (void) 00343 { 00344 cli_out_data *data = ui_out_data (current_uiout); 00345 struct ui_file *stream = VEC_last (ui_filep, data->streams); 00346 00347 fputc_filtered (' ', stream); 00348 } 00349 00350 /* This is the CLI ui-out implementation functions vector */ 00351 00352 /* FIXME: This can be initialized dynamically after default is set to 00353 handle initial output in main.c */ 00354 00355 struct ui_out_impl cli_ui_out_impl = 00356 { 00357 cli_table_begin, 00358 cli_table_body, 00359 cli_table_end, 00360 cli_table_header, 00361 cli_begin, 00362 cli_end, 00363 cli_field_int, 00364 cli_field_skip, 00365 cli_field_string, 00366 cli_field_fmt, 00367 cli_spaces, 00368 cli_text, 00369 cli_message, 00370 cli_wrap_hint, 00371 cli_flush, 00372 cli_redirect, 00373 0, 00374 0, /* Does not need MI hacks (i.e. needs CLI hacks). */ 00375 }; 00376 00377 /* Constructor for a `cli_out_data' object. */ 00378 00379 void 00380 cli_out_data_ctor (cli_out_data *self, struct ui_file *stream) 00381 { 00382 gdb_assert (stream != NULL); 00383 00384 self->streams = NULL; 00385 VEC_safe_push (ui_filep, self->streams, stream); 00386 00387 self->suppress_output = 0; 00388 } 00389 00390 /* Initialize private members at startup. */ 00391 00392 struct ui_out * 00393 cli_out_new (struct ui_file *stream) 00394 { 00395 int flags = ui_source_list; 00396 cli_out_data *data = XMALLOC (cli_out_data); 00397 00398 cli_out_data_ctor (data, stream); 00399 return ui_out_new (&cli_ui_out_impl, data, flags); 00400 } 00401 00402 struct ui_file * 00403 cli_out_set_stream (struct ui_out *uiout, struct ui_file *stream) 00404 { 00405 cli_out_data *data = ui_out_data (uiout); 00406 struct ui_file *old; 00407 00408 old = VEC_pop (ui_filep, data->streams); 00409 VEC_quick_push (ui_filep, data->streams, stream); 00410 00411 return old; 00412 }