Commit | Line | Data |
---|---|---|
fb40c209 | 1 | /* MI Command Set - output generating routines. |
b6ba6518 | 2 | Copyright 2000 Free Software Foundation, Inc. |
ab91fdd5 | 3 | Contributed by Cygnus Solutions (a Red Hat company). |
fb40c209 AC |
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 2 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, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | Boston, MA 02111-1307, USA. */ | |
21 | ||
22 | #include "defs.h" | |
23 | #include "ui-out.h" | |
24 | #include "mi-out.h" | |
25 | ||
26 | /* Convenience macro for allocting typesafe memory. */ | |
27 | ||
28 | #ifndef XMALLOC | |
29 | #define XMALLOC(TYPE) (TYPE*) xmalloc (sizeof (TYPE)) | |
30 | #endif | |
31 | ||
32 | struct ui_out_data | |
33 | { | |
59807497 | 34 | int suppress_field_separator; |
76fe6b98 | 35 | int suppress_output; |
b30bf9ee | 36 | int mi_version; |
fb40c209 AC |
37 | struct ui_file *buffer; |
38 | }; | |
39 | ||
40 | /* These are the MI output functions */ | |
41 | ||
e2e11a41 | 42 | static void mi_table_begin (struct ui_out *uiout, int nbrofcols, |
d63f1d40 | 43 | int nr_rows, const char *tblid); |
fb40c209 AC |
44 | static void mi_table_body (struct ui_out *uiout); |
45 | static void mi_table_end (struct ui_out *uiout); | |
46 | static void mi_table_header (struct ui_out *uiout, int width, | |
b25959ec | 47 | enum ui_align alig, const char *col_name, |
e2e11a41 | 48 | const char *colhdr); |
631ec795 AC |
49 | static void mi_begin (struct ui_out *uiout, enum ui_out_type type, |
50 | int level, const char *id); | |
51 | static void mi_end (struct ui_out *uiout, enum ui_out_type type, int level); | |
fb40c209 | 52 | static void mi_field_int (struct ui_out *uiout, int fldno, int width, |
e2e11a41 | 53 | enum ui_align alig, const char *fldname, int value); |
fb40c209 | 54 | static void mi_field_skip (struct ui_out *uiout, int fldno, int width, |
e2e11a41 | 55 | enum ui_align alig, const char *fldname); |
fb40c209 | 56 | static void mi_field_string (struct ui_out *uiout, int fldno, int width, |
e2e11a41 | 57 | enum ui_align alig, const char *fldname, |
fb40c209 AC |
58 | const char *string); |
59 | static void mi_field_fmt (struct ui_out *uiout, int fldno, | |
60 | int width, enum ui_align align, | |
e2e11a41 AC |
61 | const char *fldname, const char *format, |
62 | va_list args); | |
fb40c209 | 63 | static void mi_spaces (struct ui_out *uiout, int numspaces); |
e2e11a41 AC |
64 | static void mi_text (struct ui_out *uiout, const char *string); |
65 | static void mi_message (struct ui_out *uiout, int verbosity, | |
66 | const char *format, va_list args); | |
fb40c209 AC |
67 | static void mi_wrap_hint (struct ui_out *uiout, char *identstring); |
68 | static void mi_flush (struct ui_out *uiout); | |
69 | ||
70 | /* This is the MI ui-out implementation functions vector */ | |
71 | ||
72 | /* FIXME: This can be initialized dynamically after default is set to | |
73 | handle initial output in main.c */ | |
74 | ||
75 | struct ui_out_impl mi_ui_out_impl = | |
76 | { | |
77 | mi_table_begin, | |
78 | mi_table_body, | |
79 | mi_table_end, | |
80 | mi_table_header, | |
631ec795 AC |
81 | mi_begin, |
82 | mi_end, | |
fb40c209 AC |
83 | mi_field_int, |
84 | mi_field_skip, | |
85 | mi_field_string, | |
86 | mi_field_fmt, | |
87 | mi_spaces, | |
88 | mi_text, | |
89 | mi_message, | |
90 | mi_wrap_hint, | |
91 | mi_flush | |
92 | }; | |
93 | ||
94 | /* Prototypes for local functions */ | |
95 | ||
a14ed312 | 96 | extern void _initialize_mi_out (void); |
fb40c209 | 97 | static void field_separator (struct ui_out *uiout); |
d5e8ba62 AC |
98 | static void mi_open (struct ui_out *uiout, const char *name, |
99 | enum ui_out_type type); | |
9a0f0643 | 100 | static void mi_close (struct ui_out *uiout, enum ui_out_type type); |
fb40c209 AC |
101 | |
102 | static void out_field_fmt (struct ui_out *uiout, int fldno, char *fldname, | |
103 | char *format,...); | |
104 | ||
105 | /* Mark beginning of a table */ | |
106 | ||
107 | void | |
cff22675 AC |
108 | mi_table_begin (struct ui_out *uiout, |
109 | int nr_cols, | |
d63f1d40 | 110 | int nr_rows, |
e2e11a41 | 111 | const char *tblid) |
fb40c209 AC |
112 | { |
113 | struct ui_out_data *data = ui_out_data (uiout); | |
d5e8ba62 | 114 | mi_open (uiout, tblid, ui_out_type_tuple); |
cff22675 | 115 | if (data->mi_version == 0) |
76fe6b98 | 116 | { |
cff22675 AC |
117 | if (nr_rows == 0) |
118 | data->suppress_output = 1; | |
119 | else | |
120 | mi_open (uiout, "hdr", ui_out_type_list); | |
76fe6b98 AC |
121 | return; |
122 | } | |
cff22675 AC |
123 | mi_field_int (uiout, -1/*fldno*/, -1/*width*/, -1/*alin*/, |
124 | "nr_rows", nr_rows); | |
125 | mi_field_int (uiout, -1/*fldno*/, -1/*width*/, -1/*alin*/, | |
126 | "nr_cols", nr_cols); | |
127 | mi_open (uiout, "hdr", ui_out_type_list); | |
fb40c209 AC |
128 | } |
129 | ||
130 | /* Mark beginning of a table body */ | |
131 | ||
132 | void | |
fba45db2 | 133 | mi_table_body (struct ui_out *uiout) |
fb40c209 AC |
134 | { |
135 | struct ui_out_data *data = ui_out_data (uiout); | |
76fe6b98 AC |
136 | if (data->suppress_output) |
137 | return; | |
cff22675 AC |
138 | /* close the table header line if there were any headers */ |
139 | mi_close (uiout, ui_out_type_list); | |
140 | if (data->mi_version == 0) | |
141 | return; | |
142 | mi_open (uiout, "body", ui_out_type_list); | |
fb40c209 AC |
143 | } |
144 | ||
145 | /* Mark end of a table */ | |
146 | ||
147 | void | |
fba45db2 | 148 | mi_table_end (struct ui_out *uiout) |
fb40c209 AC |
149 | { |
150 | struct ui_out_data *data = ui_out_data (uiout); | |
76fe6b98 | 151 | data->suppress_output = 0; |
cff22675 AC |
152 | if (data->mi_version == 0) |
153 | { | |
154 | mi_close (uiout, ui_out_type_tuple); | |
155 | return; | |
156 | } | |
157 | mi_close (uiout, ui_out_type_list); /* body */ | |
666547aa | 158 | mi_close (uiout, ui_out_type_tuple); |
fb40c209 AC |
159 | } |
160 | ||
161 | /* Specify table header */ | |
162 | ||
163 | void | |
e2e11a41 | 164 | mi_table_header (struct ui_out *uiout, int width, int alignment, |
b25959ec | 165 | const char *col_name, |
e2e11a41 | 166 | const char *colhdr) |
fb40c209 AC |
167 | { |
168 | struct ui_out_data *data = ui_out_data (uiout); | |
76fe6b98 AC |
169 | if (data->suppress_output) |
170 | return; | |
cff22675 AC |
171 | if (data->mi_version == 0) |
172 | { | |
173 | mi_field_string (uiout, 0, width, alignment, 0, colhdr); | |
174 | return; | |
175 | } | |
176 | mi_open (uiout, NULL, ui_out_type_tuple); | |
177 | mi_field_int (uiout, 0, 0, 0, "width", width); | |
178 | mi_field_int (uiout, 0, 0, 0, "alignment", alignment); | |
179 | mi_field_string (uiout, 0, 0, 0, "col_name", col_name); | |
180 | mi_field_string (uiout, 0, width, alignment, "colhdr", colhdr); | |
181 | mi_close (uiout, ui_out_type_tuple); | |
fb40c209 AC |
182 | } |
183 | ||
184 | /* Mark beginning of a list */ | |
185 | ||
186 | void | |
631ec795 AC |
187 | mi_begin (struct ui_out *uiout, |
188 | enum ui_out_type type, | |
189 | int level, | |
9a0f0643 | 190 | const char *id) |
fb40c209 AC |
191 | { |
192 | struct ui_out_data *data = ui_out_data (uiout); | |
76fe6b98 AC |
193 | if (data->suppress_output) |
194 | return; | |
d5e8ba62 | 195 | mi_open (uiout, id, type); |
fb40c209 AC |
196 | } |
197 | ||
198 | /* Mark end of a list */ | |
199 | ||
200 | void | |
631ec795 AC |
201 | mi_end (struct ui_out *uiout, |
202 | enum ui_out_type type, | |
203 | int level) | |
fb40c209 AC |
204 | { |
205 | struct ui_out_data *data = ui_out_data (uiout); | |
76fe6b98 AC |
206 | if (data->suppress_output) |
207 | return; | |
9a0f0643 | 208 | mi_close (uiout, type); |
fb40c209 AC |
209 | } |
210 | ||
211 | /* output an int field */ | |
212 | ||
213 | void | |
fba45db2 | 214 | mi_field_int (struct ui_out *uiout, int fldno, int width, int alignment, |
e2e11a41 | 215 | const char *fldname, int value) |
fb40c209 AC |
216 | { |
217 | char buffer[20]; /* FIXME: how many chars long a %d can become? */ | |
76fe6b98 AC |
218 | struct ui_out_data *data = ui_out_data (uiout); |
219 | if (data->suppress_output) | |
220 | return; | |
fb40c209 AC |
221 | |
222 | sprintf (buffer, "%d", value); | |
223 | mi_field_string (uiout, fldno, width, alignment, fldname, buffer); | |
224 | } | |
225 | ||
226 | /* used to ommit a field */ | |
227 | ||
228 | void | |
fba45db2 | 229 | mi_field_skip (struct ui_out *uiout, int fldno, int width, int alignment, |
e2e11a41 | 230 | const char *fldname) |
fb40c209 | 231 | { |
76fe6b98 AC |
232 | struct ui_out_data *data = ui_out_data (uiout); |
233 | if (data->suppress_output) | |
234 | return; | |
fb40c209 AC |
235 | mi_field_string (uiout, fldno, width, alignment, fldname, ""); |
236 | } | |
237 | ||
238 | /* other specific mi_field_* end up here so alignment and field | |
239 | separators are both handled by mi_field_string */ | |
240 | ||
241 | void | |
242 | mi_field_string (struct ui_out *uiout, | |
243 | int fldno, | |
244 | int width, | |
245 | int align, | |
e2e11a41 | 246 | const char *fldname, |
fb40c209 AC |
247 | const char *string) |
248 | { | |
249 | struct ui_out_data *data = ui_out_data (uiout); | |
76fe6b98 AC |
250 | if (data->suppress_output) |
251 | return; | |
fb40c209 AC |
252 | field_separator (uiout); |
253 | if (fldname) | |
254 | fprintf_unfiltered (data->buffer, "%s=", fldname); | |
255 | fprintf_unfiltered (data->buffer, "\""); | |
256 | if (string) | |
257 | fputstr_unfiltered (string, '"', data->buffer); | |
258 | fprintf_unfiltered (data->buffer, "\""); | |
259 | } | |
260 | ||
261 | /* This is the only field function that does not align */ | |
262 | ||
263 | void | |
264 | mi_field_fmt (struct ui_out *uiout, int fldno, | |
265 | int width, enum ui_align align, | |
e2e11a41 AC |
266 | const char *fldname, |
267 | const char *format, | |
268 | va_list args) | |
fb40c209 AC |
269 | { |
270 | struct ui_out_data *data = ui_out_data (uiout); | |
76fe6b98 AC |
271 | if (data->suppress_output) |
272 | return; | |
fb40c209 AC |
273 | field_separator (uiout); |
274 | if (fldname) | |
275 | fprintf_unfiltered (data->buffer, "%s=\"", fldname); | |
276 | else | |
277 | fputs_unfiltered ("\"", data->buffer); | |
278 | vfprintf_unfiltered (data->buffer, format, args); | |
279 | fputs_unfiltered ("\"", data->buffer); | |
280 | } | |
281 | ||
282 | void | |
fba45db2 | 283 | mi_spaces (struct ui_out *uiout, int numspaces) |
fb40c209 AC |
284 | { |
285 | } | |
286 | ||
287 | void | |
e2e11a41 | 288 | mi_text (struct ui_out *uiout, const char *string) |
fb40c209 AC |
289 | { |
290 | } | |
291 | ||
292 | void | |
e2e11a41 AC |
293 | mi_message (struct ui_out *uiout, int verbosity, |
294 | const char *format, | |
295 | va_list args) | |
fb40c209 AC |
296 | { |
297 | } | |
298 | ||
299 | void | |
fba45db2 | 300 | mi_wrap_hint (struct ui_out *uiout, char *identstring) |
fb40c209 AC |
301 | { |
302 | wrap_here (identstring); | |
303 | } | |
304 | ||
305 | void | |
fba45db2 | 306 | mi_flush (struct ui_out *uiout) |
fb40c209 AC |
307 | { |
308 | struct ui_out_data *data = ui_out_data (uiout); | |
309 | gdb_flush (data->buffer); | |
310 | } | |
311 | ||
312 | /* local functions */ | |
313 | ||
314 | /* Like mi_field_fmt, but takes a variable number of args | |
315 | and makes a va_list and does not insert a separator */ | |
316 | ||
317 | /* VARARGS */ | |
318 | static void | |
319 | out_field_fmt (struct ui_out *uiout, int fldno, char *fldname, | |
320 | char *format,...) | |
321 | { | |
322 | struct ui_out_data *data = ui_out_data (uiout); | |
323 | va_list args; | |
324 | ||
325 | field_separator (uiout); | |
326 | if (fldname) | |
327 | fprintf_unfiltered (data->buffer, "%s=\"", fldname); | |
328 | else | |
329 | fputs_unfiltered ("\"", data->buffer); | |
330 | ||
331 | va_start (args, format); | |
332 | vfprintf_unfiltered (data->buffer, format, args); | |
333 | ||
334 | fputs_unfiltered ("\"", data->buffer); | |
335 | ||
336 | va_end (args); | |
337 | } | |
338 | ||
339 | /* access to ui_out format private members */ | |
340 | ||
341 | static void | |
342 | field_separator (struct ui_out *uiout) | |
343 | { | |
344 | struct ui_out_data *data = ui_out_data (uiout); | |
59807497 AC |
345 | if (data->suppress_field_separator) |
346 | data->suppress_field_separator = 0; | |
fb40c209 AC |
347 | else |
348 | fputc_unfiltered (',', data->buffer); | |
349 | } | |
350 | ||
351 | static void | |
9a0f0643 | 352 | mi_open (struct ui_out *uiout, |
d5e8ba62 | 353 | const char *name, |
9a0f0643 | 354 | enum ui_out_type type) |
fb40c209 AC |
355 | { |
356 | struct ui_out_data *data = ui_out_data (uiout); | |
d5e8ba62 | 357 | field_separator (uiout); |
59807497 | 358 | data->suppress_field_separator = 1; |
d5e8ba62 AC |
359 | if (name) |
360 | fprintf_unfiltered (data->buffer, "%s=", name); | |
5a9aa5dc AC |
361 | switch (type) |
362 | { | |
363 | case ui_out_type_tuple: | |
364 | fputc_unfiltered ('{', data->buffer); | |
365 | break; | |
366 | case ui_out_type_list: | |
cff22675 | 367 | if (data->mi_version == 0) |
a7c14aa5 | 368 | fputc_unfiltered ('{', data->buffer); |
cff22675 AC |
369 | else |
370 | fputc_unfiltered ('[', data->buffer); | |
5a9aa5dc AC |
371 | break; |
372 | default: | |
373 | internal_error (__FILE__, __LINE__, "bad switch"); | |
374 | } | |
fb40c209 AC |
375 | } |
376 | ||
377 | static void | |
9a0f0643 AC |
378 | mi_close (struct ui_out *uiout, |
379 | enum ui_out_type type) | |
fb40c209 AC |
380 | { |
381 | struct ui_out_data *data = ui_out_data (uiout); | |
5a9aa5dc AC |
382 | switch (type) |
383 | { | |
384 | case ui_out_type_tuple: | |
385 | fputc_unfiltered ('}', data->buffer); | |
386 | break; | |
387 | case ui_out_type_list: | |
cff22675 | 388 | if (data->mi_version == 0) |
a7c14aa5 | 389 | fputc_unfiltered ('}', data->buffer); |
cff22675 AC |
390 | else |
391 | fputc_unfiltered (']', data->buffer); | |
5a9aa5dc AC |
392 | break; |
393 | default: | |
394 | internal_error (__FILE__, __LINE__, "bad switch"); | |
395 | } | |
59807497 | 396 | data->suppress_field_separator = 0; |
fb40c209 AC |
397 | } |
398 | ||
399 | /* add a string to the buffer */ | |
400 | ||
401 | void | |
402 | mi_out_buffered (struct ui_out *uiout, char *string) | |
403 | { | |
404 | struct ui_out_data *data = ui_out_data (uiout); | |
405 | fprintf_unfiltered (data->buffer, "%s", string); | |
406 | } | |
407 | ||
408 | /* clear the buffer */ | |
409 | ||
410 | void | |
411 | mi_out_rewind (struct ui_out *uiout) | |
412 | { | |
413 | struct ui_out_data *data = ui_out_data (uiout); | |
414 | ui_file_rewind (data->buffer); | |
415 | } | |
416 | ||
417 | /* dump the buffer onto the specified stream */ | |
418 | ||
419 | static void | |
420 | do_write (void *data, const char *buffer, long length_buffer) | |
421 | { | |
422 | ui_file_write (data, buffer, length_buffer); | |
423 | } | |
424 | ||
425 | void | |
426 | mi_out_put (struct ui_out *uiout, | |
427 | struct ui_file *stream) | |
428 | { | |
429 | struct ui_out_data *data = ui_out_data (uiout); | |
430 | ui_file_put (data->buffer, do_write, stream); | |
431 | ui_file_rewind (data->buffer); | |
432 | } | |
433 | ||
434 | /* initalize private members at startup */ | |
435 | ||
436 | struct ui_out * | |
b30bf9ee | 437 | mi_out_new (int mi_version) |
fb40c209 AC |
438 | { |
439 | int flags = 0; | |
440 | struct ui_out_data *data = XMALLOC (struct ui_out_data); | |
59807497 | 441 | data->suppress_field_separator = 0; |
b30bf9ee | 442 | data->mi_version = mi_version; |
fb40c209 AC |
443 | /* FIXME: This code should be using a ``string_file'' and not the |
444 | TUI buffer hack. */ | |
445 | data->buffer = mem_fileopen (); | |
446 | return ui_out_new (&mi_ui_out_impl, data, flags); | |
447 | } | |
448 | ||
449 | /* standard gdb initialization hook */ | |
450 | void | |
fba45db2 | 451 | _initialize_mi_out (void) |
fb40c209 AC |
452 | { |
453 | /* nothing happens here */ | |
454 | } |