]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/guile/scm-pretty-print.c
Change all_objfiles adapter to be a method on program_space
[thirdparty/binutils-gdb.git] / gdb / guile / scm-pretty-print.c
1 /* GDB/Scheme pretty-printing.
2
3 Copyright (C) 2008-2019 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 /* See README file in this directory for implementation notes, coding
21 conventions, et.al. */
22
23 #include "defs.h"
24 #include "charset.h"
25 #include "symtab.h" /* Needed by language.h. */
26 #include "language.h"
27 #include "objfiles.h"
28 #include "value.h"
29 #include "valprint.h"
30 #include "guile-internal.h"
31
32 /* Return type of print_string_repr. */
33
34 enum string_repr_result
35 {
36 /* The string method returned None. */
37 STRING_REPR_NONE,
38 /* The string method had an error. */
39 STRING_REPR_ERROR,
40 /* Everything ok. */
41 STRING_REPR_OK
42 };
43
44 /* Display hints. */
45
46 enum display_hint
47 {
48 /* No display hint. */
49 HINT_NONE,
50 /* The display hint has a bad value. */
51 HINT_ERROR,
52 /* Print as an array. */
53 HINT_ARRAY,
54 /* Print as a map. */
55 HINT_MAP,
56 /* Print as a string. */
57 HINT_STRING
58 };
59
60 /* The <gdb:pretty-printer> smob. */
61
62 typedef struct
63 {
64 /* This must appear first. */
65 gdb_smob base;
66
67 /* A string representing the name of the printer. */
68 SCM name;
69
70 /* A boolean indicating whether the printer is enabled. */
71 SCM enabled;
72
73 /* A procedure called to look up the printer for the given value.
74 The procedure is called as (lookup gdb:pretty-printer value).
75 The result should either be a gdb:pretty-printer object that will print
76 the value, or #f if the value is not recognized. */
77 SCM lookup;
78
79 /* Note: Attaching subprinters to this smob is left to Scheme. */
80 } pretty_printer_smob;
81
82 /* The <gdb:pretty-printer-worker> smob. */
83
84 typedef struct
85 {
86 /* This must appear first. */
87 gdb_smob base;
88
89 /* Either #f or one of the supported display hints: map, array, string.
90 If neither of those then the display hint is ignored (treated as #f). */
91 SCM display_hint;
92
93 /* A procedure called to pretty-print the value.
94 (lambda (printer) ...) -> string | <gdb:lazy-string> | <gdb:value> */
95 SCM to_string;
96
97 /* A procedure called to print children of the value.
98 (lambda (printer) ...) -> <gdb:iterator>
99 The iterator returns a pair for each iteration: (name . value),
100 where "value" can have the same types as to_string. */
101 SCM children;
102 } pretty_printer_worker_smob;
103
104 static const char pretty_printer_smob_name[] =
105 "gdb:pretty-printer";
106 static const char pretty_printer_worker_smob_name[] =
107 "gdb:pretty-printer-worker";
108
109 /* The tag Guile knows the pretty-printer smobs by. */
110 static scm_t_bits pretty_printer_smob_tag;
111 static scm_t_bits pretty_printer_worker_smob_tag;
112
113 /* The global pretty-printer list. */
114 static SCM pretty_printer_list;
115
116 /* gdb:pp-type-error. */
117 static SCM pp_type_error_symbol;
118
119 /* Pretty-printer display hints are specified by strings. */
120 static SCM ppscm_map_string;
121 static SCM ppscm_array_string;
122 static SCM ppscm_string_string;
123 \f
124 /* Administrivia for pretty-printer matcher smobs. */
125
126 /* The smob "print" function for <gdb:pretty-printer>. */
127
128 static int
129 ppscm_print_pretty_printer_smob (SCM self, SCM port, scm_print_state *pstate)
130 {
131 pretty_printer_smob *pp_smob = (pretty_printer_smob *) SCM_SMOB_DATA (self);
132
133 gdbscm_printf (port, "#<%s ", pretty_printer_smob_name);
134 scm_write (pp_smob->name, port);
135 scm_puts (gdbscm_is_true (pp_smob->enabled) ? " enabled" : " disabled",
136 port);
137 scm_puts (">", port);
138
139 scm_remember_upto_here_1 (self);
140
141 /* Non-zero means success. */
142 return 1;
143 }
144
145 /* (make-pretty-printer string procedure) -> <gdb:pretty-printer> */
146
147 static SCM
148 gdbscm_make_pretty_printer (SCM name, SCM lookup)
149 {
150 pretty_printer_smob *pp_smob = (pretty_printer_smob *)
151 scm_gc_malloc (sizeof (pretty_printer_smob),
152 pretty_printer_smob_name);
153 SCM smob;
154
155 SCM_ASSERT_TYPE (scm_is_string (name), name, SCM_ARG1, FUNC_NAME,
156 _("string"));
157 SCM_ASSERT_TYPE (gdbscm_is_procedure (lookup), lookup, SCM_ARG2, FUNC_NAME,
158 _("procedure"));
159
160 pp_smob->name = name;
161 pp_smob->lookup = lookup;
162 pp_smob->enabled = SCM_BOOL_T;
163 smob = scm_new_smob (pretty_printer_smob_tag, (scm_t_bits) pp_smob);
164 gdbscm_init_gsmob (&pp_smob->base);
165
166 return smob;
167 }
168
169 /* Return non-zero if SCM is a <gdb:pretty-printer> object. */
170
171 static int
172 ppscm_is_pretty_printer (SCM scm)
173 {
174 return SCM_SMOB_PREDICATE (pretty_printer_smob_tag, scm);
175 }
176
177 /* (pretty-printer? object) -> boolean */
178
179 static SCM
180 gdbscm_pretty_printer_p (SCM scm)
181 {
182 return scm_from_bool (ppscm_is_pretty_printer (scm));
183 }
184
185 /* Returns the <gdb:pretty-printer> object in SELF.
186 Throws an exception if SELF is not a <gdb:pretty-printer> object. */
187
188 static SCM
189 ppscm_get_pretty_printer_arg_unsafe (SCM self, int arg_pos,
190 const char *func_name)
191 {
192 SCM_ASSERT_TYPE (ppscm_is_pretty_printer (self), self, arg_pos, func_name,
193 pretty_printer_smob_name);
194
195 return self;
196 }
197
198 /* Returns a pointer to the pretty-printer smob of SELF.
199 Throws an exception if SELF is not a <gdb:pretty-printer> object. */
200
201 static pretty_printer_smob *
202 ppscm_get_pretty_printer_smob_arg_unsafe (SCM self, int arg_pos,
203 const char *func_name)
204 {
205 SCM pp_scm = ppscm_get_pretty_printer_arg_unsafe (self, arg_pos, func_name);
206 pretty_printer_smob *pp_smob
207 = (pretty_printer_smob *) SCM_SMOB_DATA (pp_scm);
208
209 return pp_smob;
210 }
211 \f
212 /* Pretty-printer methods. */
213
214 /* (pretty-printer-enabled? <gdb:pretty-printer>) -> boolean */
215
216 static SCM
217 gdbscm_pretty_printer_enabled_p (SCM self)
218 {
219 pretty_printer_smob *pp_smob
220 = ppscm_get_pretty_printer_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
221
222 return pp_smob->enabled;
223 }
224
225 /* (set-pretty-printer-enabled! <gdb:pretty-printer> boolean)
226 -> unspecified */
227
228 static SCM
229 gdbscm_set_pretty_printer_enabled_x (SCM self, SCM enabled)
230 {
231 pretty_printer_smob *pp_smob
232 = ppscm_get_pretty_printer_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
233
234 pp_smob->enabled = scm_from_bool (gdbscm_is_true (enabled));
235
236 return SCM_UNSPECIFIED;
237 }
238
239 /* (pretty-printers) -> list
240 Returns the list of global pretty-printers. */
241
242 static SCM
243 gdbscm_pretty_printers (void)
244 {
245 return pretty_printer_list;
246 }
247
248 /* (set-pretty-printers! list) -> unspecified
249 Set the global pretty-printers list. */
250
251 static SCM
252 gdbscm_set_pretty_printers_x (SCM printers)
253 {
254 SCM_ASSERT_TYPE (gdbscm_is_true (scm_list_p (printers)), printers,
255 SCM_ARG1, FUNC_NAME, _("list"));
256
257 pretty_printer_list = printers;
258
259 return SCM_UNSPECIFIED;
260 }
261 \f
262 /* Administrivia for pretty-printer-worker smobs.
263 These are created when a matcher recognizes a value. */
264
265 /* The smob "print" function for <gdb:pretty-printer-worker>. */
266
267 static int
268 ppscm_print_pretty_printer_worker_smob (SCM self, SCM port,
269 scm_print_state *pstate)
270 {
271 pretty_printer_worker_smob *w_smob
272 = (pretty_printer_worker_smob *) SCM_SMOB_DATA (self);
273
274 gdbscm_printf (port, "#<%s ", pretty_printer_worker_smob_name);
275 scm_write (w_smob->display_hint, port);
276 scm_puts (" ", port);
277 scm_write (w_smob->to_string, port);
278 scm_puts (" ", port);
279 scm_write (w_smob->children, port);
280 scm_puts (">", port);
281
282 scm_remember_upto_here_1 (self);
283
284 /* Non-zero means success. */
285 return 1;
286 }
287
288 /* (make-pretty-printer-worker string procedure procedure)
289 -> <gdb:pretty-printer-worker> */
290
291 static SCM
292 gdbscm_make_pretty_printer_worker (SCM display_hint, SCM to_string,
293 SCM children)
294 {
295 pretty_printer_worker_smob *w_smob = (pretty_printer_worker_smob *)
296 scm_gc_malloc (sizeof (pretty_printer_worker_smob),
297 pretty_printer_worker_smob_name);
298 SCM w_scm;
299
300 w_smob->display_hint = display_hint;
301 w_smob->to_string = to_string;
302 w_smob->children = children;
303 w_scm = scm_new_smob (pretty_printer_worker_smob_tag, (scm_t_bits) w_smob);
304 gdbscm_init_gsmob (&w_smob->base);
305 return w_scm;
306 }
307
308 /* Return non-zero if SCM is a <gdb:pretty-printer-worker> object. */
309
310 static int
311 ppscm_is_pretty_printer_worker (SCM scm)
312 {
313 return SCM_SMOB_PREDICATE (pretty_printer_worker_smob_tag, scm);
314 }
315
316 /* (pretty-printer-worker? object) -> boolean */
317
318 static SCM
319 gdbscm_pretty_printer_worker_p (SCM scm)
320 {
321 return scm_from_bool (ppscm_is_pretty_printer_worker (scm));
322 }
323 \f
324 /* Helper function to create a <gdb:exception> object indicating that the
325 type of some value returned from a pretty-printer is invalid. */
326
327 static SCM
328 ppscm_make_pp_type_error_exception (const char *message, SCM object)
329 {
330 std::string msg = string_printf ("%s: ~S", message);
331 return gdbscm_make_error (pp_type_error_symbol,
332 NULL /* func */, msg.c_str (),
333 scm_list_1 (object), scm_list_1 (object));
334 }
335
336 /* Print MESSAGE as an exception (meaning it is controlled by
337 "guile print-stack").
338 Called from the printer code when the Scheme code returns an invalid type
339 for something. */
340
341 static void
342 ppscm_print_pp_type_error (const char *message, SCM object)
343 {
344 SCM exception = ppscm_make_pp_type_error_exception (message, object);
345
346 gdbscm_print_gdb_exception (SCM_BOOL_F, exception);
347 }
348
349 /* Helper function for find_pretty_printer which iterates over a list,
350 calls each function and inspects output. This will return a
351 <gdb:pretty-printer> object if one recognizes VALUE. If no printer is
352 found, it will return #f. On error, it will return a <gdb:exception>
353 object.
354
355 Note: This has to be efficient and careful.
356 We don't want to excessively slow down printing of values, but any kind of
357 random crud can appear in the pretty-printer list, and we can't crash
358 because of it. */
359
360 static SCM
361 ppscm_search_pp_list (SCM list, SCM value)
362 {
363 SCM orig_list = list;
364
365 if (scm_is_null (list))
366 return SCM_BOOL_F;
367 if (gdbscm_is_false (scm_list_p (list))) /* scm_is_pair? */
368 {
369 return ppscm_make_pp_type_error_exception
370 (_("pretty-printer list is not a list"), list);
371 }
372
373 for ( ; scm_is_pair (list); list = scm_cdr (list))
374 {
375 SCM matcher = scm_car (list);
376 SCM worker;
377 pretty_printer_smob *pp_smob;
378
379 if (!ppscm_is_pretty_printer (matcher))
380 {
381 return ppscm_make_pp_type_error_exception
382 (_("pretty-printer list contains non-pretty-printer object"),
383 matcher);
384 }
385
386 pp_smob = (pretty_printer_smob *) SCM_SMOB_DATA (matcher);
387
388 /* Skip if disabled. */
389 if (gdbscm_is_false (pp_smob->enabled))
390 continue;
391
392 if (!gdbscm_is_procedure (pp_smob->lookup))
393 {
394 return ppscm_make_pp_type_error_exception
395 (_("invalid lookup object in pretty-printer matcher"),
396 pp_smob->lookup);
397 }
398
399 worker = gdbscm_safe_call_2 (pp_smob->lookup, matcher,
400 value, gdbscm_memory_error_p);
401 if (!gdbscm_is_false (worker))
402 {
403 if (gdbscm_is_exception (worker))
404 return worker;
405 if (ppscm_is_pretty_printer_worker (worker))
406 return worker;
407 return ppscm_make_pp_type_error_exception
408 (_("invalid result from pretty-printer lookup"), worker);
409 }
410 }
411
412 if (!scm_is_null (list))
413 {
414 return ppscm_make_pp_type_error_exception
415 (_("pretty-printer list is not a list"), orig_list);
416 }
417
418 return SCM_BOOL_F;
419 }
420
421 /* Subroutine of find_pretty_printer to simplify it.
422 Look for a pretty-printer to print VALUE in all objfiles.
423 If there's an error an exception smob is returned.
424 The result is #f, if no pretty-printer was found.
425 Otherwise the result is the pretty-printer smob. */
426
427 static SCM
428 ppscm_find_pretty_printer_from_objfiles (SCM value)
429 {
430 for (objfile *objfile : current_program_space->objfiles ())
431 {
432 objfile_smob *o_smob = ofscm_objfile_smob_from_objfile (objfile);
433 SCM pp
434 = ppscm_search_pp_list (ofscm_objfile_smob_pretty_printers (o_smob),
435 value);
436
437 /* Note: This will return if pp is a <gdb:exception> object,
438 which is what we want. */
439 if (gdbscm_is_true (pp))
440 return pp;
441 }
442
443 return SCM_BOOL_F;
444 }
445
446 /* Subroutine of find_pretty_printer to simplify it.
447 Look for a pretty-printer to print VALUE in the current program space.
448 If there's an error an exception smob is returned.
449 The result is #f, if no pretty-printer was found.
450 Otherwise the result is the pretty-printer smob. */
451
452 static SCM
453 ppscm_find_pretty_printer_from_progspace (SCM value)
454 {
455 pspace_smob *p_smob = psscm_pspace_smob_from_pspace (current_program_space);
456 SCM pp
457 = ppscm_search_pp_list (psscm_pspace_smob_pretty_printers (p_smob), value);
458
459 return pp;
460 }
461
462 /* Subroutine of find_pretty_printer to simplify it.
463 Look for a pretty-printer to print VALUE in the gdb module.
464 If there's an error a Scheme exception is returned.
465 The result is #f, if no pretty-printer was found.
466 Otherwise the result is the pretty-printer smob. */
467
468 static SCM
469 ppscm_find_pretty_printer_from_gdb (SCM value)
470 {
471 SCM pp = ppscm_search_pp_list (pretty_printer_list, value);
472
473 return pp;
474 }
475
476 /* Find the pretty-printing constructor function for VALUE. If no
477 pretty-printer exists, return #f. If one exists, return the
478 gdb:pretty-printer smob that implements it. On error, an exception smob
479 is returned.
480
481 Note: In the end it may be better to call out to Scheme once, and then
482 do all of the lookup from Scheme. TBD. */
483
484 static SCM
485 ppscm_find_pretty_printer (SCM value)
486 {
487 SCM pp;
488
489 /* Look at the pretty-printer list for each objfile
490 in the current program-space. */
491 pp = ppscm_find_pretty_printer_from_objfiles (value);
492 /* Note: This will return if function is a <gdb:exception> object,
493 which is what we want. */
494 if (gdbscm_is_true (pp))
495 return pp;
496
497 /* Look at the pretty-printer list for the current program-space. */
498 pp = ppscm_find_pretty_printer_from_progspace (value);
499 /* Note: This will return if function is a <gdb:exception> object,
500 which is what we want. */
501 if (gdbscm_is_true (pp))
502 return pp;
503
504 /* Look at the pretty-printer list in the gdb module. */
505 pp = ppscm_find_pretty_printer_from_gdb (value);
506 return pp;
507 }
508
509 /* Pretty-print a single value, via the PRINTER, which must be a
510 <gdb:pretty-printer-worker> object.
511 The caller is responsible for ensuring PRINTER is valid.
512 If the function returns a string, an SCM containing the string
513 is returned. If the function returns #f that means the pretty
514 printer returned #f as a value. Otherwise, if the function returns a
515 <gdb:value> object, *OUT_VALUE is set to the value and #t is returned.
516 It is an error if the printer returns #t.
517 On error, an exception smob is returned. */
518
519 static SCM
520 ppscm_pretty_print_one_value (SCM printer, struct value **out_value,
521 struct gdbarch *gdbarch,
522 const struct language_defn *language)
523 {
524 SCM result = SCM_BOOL_F;
525
526 *out_value = NULL;
527 TRY
528 {
529 pretty_printer_worker_smob *w_smob
530 = (pretty_printer_worker_smob *) SCM_SMOB_DATA (printer);
531
532 result = gdbscm_safe_call_1 (w_smob->to_string, printer,
533 gdbscm_memory_error_p);
534 if (gdbscm_is_false (result))
535 ; /* Done. */
536 else if (scm_is_string (result)
537 || lsscm_is_lazy_string (result))
538 ; /* Done. */
539 else if (vlscm_is_value (result))
540 {
541 SCM except_scm;
542
543 *out_value
544 = vlscm_convert_value_from_scheme (FUNC_NAME, GDBSCM_ARG_NONE,
545 result, &except_scm,
546 gdbarch, language);
547 if (*out_value != NULL)
548 result = SCM_BOOL_T;
549 else
550 result = except_scm;
551 }
552 else if (gdbscm_is_exception (result))
553 ; /* Done. */
554 else
555 {
556 /* Invalid result from to-string. */
557 result = ppscm_make_pp_type_error_exception
558 (_("invalid result from pretty-printer to-string"), result);
559 }
560 }
561 CATCH (except, RETURN_MASK_ALL)
562 {
563 }
564 END_CATCH
565
566 return result;
567 }
568
569 /* Return the display hint for PRINTER as a Scheme object.
570 The caller is responsible for ensuring PRINTER is a
571 <gdb:pretty-printer-worker> object. */
572
573 static SCM
574 ppscm_get_display_hint_scm (SCM printer)
575 {
576 pretty_printer_worker_smob *w_smob
577 = (pretty_printer_worker_smob *) SCM_SMOB_DATA (printer);
578
579 return w_smob->display_hint;
580 }
581
582 /* Return the display hint for the pretty-printer PRINTER.
583 The caller is responsible for ensuring PRINTER is a
584 <gdb:pretty-printer-worker> object.
585 Returns the display hint or #f if the hint is not a string. */
586
587 static enum display_hint
588 ppscm_get_display_hint_enum (SCM printer)
589 {
590 SCM hint = ppscm_get_display_hint_scm (printer);
591
592 if (gdbscm_is_false (hint))
593 return HINT_NONE;
594 if (scm_is_string (hint))
595 {
596 if (gdbscm_is_true (scm_string_equal_p (hint, ppscm_array_string)))
597 return HINT_STRING;
598 if (gdbscm_is_true (scm_string_equal_p (hint, ppscm_map_string)))
599 return HINT_STRING;
600 if (gdbscm_is_true (scm_string_equal_p (hint, ppscm_string_string)))
601 return HINT_STRING;
602 return HINT_ERROR;
603 }
604 return HINT_ERROR;
605 }
606
607 /* A wrapper for gdbscm_print_gdb_exception that ignores memory errors.
608 EXCEPTION is a <gdb:exception> object. */
609
610 static void
611 ppscm_print_exception_unless_memory_error (SCM exception,
612 struct ui_file *stream)
613 {
614 if (gdbscm_memory_error_p (gdbscm_exception_key (exception)))
615 {
616 gdb::unique_xmalloc_ptr<char> msg
617 = gdbscm_exception_message_to_string (exception);
618
619 /* This "shouldn't happen", but play it safe. */
620 if (msg == NULL || msg.get ()[0] == '\0')
621 fprintf_filtered (stream, _("<error reading variable>"));
622 else
623 {
624 /* Remove the trailing newline. We could instead call a special
625 routine for printing memory error messages, but this is easy
626 enough for now. */
627 char *msg_text = msg.get ();
628 size_t len = strlen (msg_text);
629
630 if (msg_text[len - 1] == '\n')
631 msg_text[len - 1] = '\0';
632 fprintf_filtered (stream, _("<error reading variable: %s>"), msg_text);
633 }
634 }
635 else
636 gdbscm_print_gdb_exception (SCM_BOOL_F, exception);
637 }
638
639 /* Helper for gdbscm_apply_val_pretty_printer which calls to_string and
640 formats the result. */
641
642 static enum string_repr_result
643 ppscm_print_string_repr (SCM printer, enum display_hint hint,
644 struct ui_file *stream, int recurse,
645 const struct value_print_options *options,
646 struct gdbarch *gdbarch,
647 const struct language_defn *language)
648 {
649 struct value *replacement = NULL;
650 SCM str_scm;
651 enum string_repr_result result = STRING_REPR_ERROR;
652
653 str_scm = ppscm_pretty_print_one_value (printer, &replacement,
654 gdbarch, language);
655 if (gdbscm_is_false (str_scm))
656 {
657 result = STRING_REPR_NONE;
658 }
659 else if (scm_is_eq (str_scm, SCM_BOOL_T))
660 {
661 struct value_print_options opts = *options;
662
663 gdb_assert (replacement != NULL);
664 opts.addressprint = 0;
665 common_val_print (replacement, stream, recurse, &opts, language);
666 result = STRING_REPR_OK;
667 }
668 else if (scm_is_string (str_scm))
669 {
670 size_t length;
671 gdb::unique_xmalloc_ptr<char> string
672 = gdbscm_scm_to_string (str_scm, &length,
673 target_charset (gdbarch), 0 /*!strict*/, NULL);
674
675 if (hint == HINT_STRING)
676 {
677 struct type *type = builtin_type (gdbarch)->builtin_char;
678
679 LA_PRINT_STRING (stream, type, (gdb_byte *) string.get (),
680 length, NULL, 0, options);
681 }
682 else
683 {
684 /* Alas scm_to_stringn doesn't nul-terminate the string if we
685 ask for the length. */
686 size_t i;
687
688 for (i = 0; i < length; ++i)
689 {
690 if (string.get ()[i] == '\0')
691 fputs_filtered ("\\000", stream);
692 else
693 fputc_filtered (string.get ()[i], stream);
694 }
695 }
696 result = STRING_REPR_OK;
697 }
698 else if (lsscm_is_lazy_string (str_scm))
699 {
700 struct value_print_options local_opts = *options;
701
702 local_opts.addressprint = 0;
703 lsscm_val_print_lazy_string (str_scm, stream, &local_opts);
704 result = STRING_REPR_OK;
705 }
706 else
707 {
708 gdb_assert (gdbscm_is_exception (str_scm));
709 ppscm_print_exception_unless_memory_error (str_scm, stream);
710 result = STRING_REPR_ERROR;
711 }
712
713 return result;
714 }
715
716 /* Helper for gdbscm_apply_val_pretty_printer that formats children of the
717 printer, if any exist.
718 The caller is responsible for ensuring PRINTER is a printer smob.
719 If PRINTED_NOTHING is true, then nothing has been printed by to_string,
720 and format output accordingly. */
721
722 static void
723 ppscm_print_children (SCM printer, enum display_hint hint,
724 struct ui_file *stream, int recurse,
725 const struct value_print_options *options,
726 struct gdbarch *gdbarch,
727 const struct language_defn *language,
728 int printed_nothing)
729 {
730 pretty_printer_worker_smob *w_smob
731 = (pretty_printer_worker_smob *) SCM_SMOB_DATA (printer);
732 int is_map, is_array, done_flag, pretty;
733 unsigned int i;
734 SCM children;
735 SCM iter = SCM_BOOL_F; /* -Wall */
736
737 if (gdbscm_is_false (w_smob->children))
738 return;
739 if (!gdbscm_is_procedure (w_smob->children))
740 {
741 ppscm_print_pp_type_error
742 (_("pretty-printer \"children\" object is not a procedure or #f"),
743 w_smob->children);
744 return;
745 }
746
747 /* If we are printing a map or an array, we want special formatting. */
748 is_map = hint == HINT_MAP;
749 is_array = hint == HINT_ARRAY;
750
751 children = gdbscm_safe_call_1 (w_smob->children, printer,
752 gdbscm_memory_error_p);
753 if (gdbscm_is_exception (children))
754 {
755 ppscm_print_exception_unless_memory_error (children, stream);
756 goto done;
757 }
758 /* We combine two steps here: get children, make an iterator out of them.
759 This simplifies things because there's no language means of creating
760 iterators, and it's the printer object that knows how it will want its
761 children iterated over. */
762 if (!itscm_is_iterator (children))
763 {
764 ppscm_print_pp_type_error
765 (_("result of pretty-printer \"children\" procedure is not"
766 " a <gdb:iterator> object"), children);
767 goto done;
768 }
769 iter = children;
770
771 /* Use the prettyformat_arrays option if we are printing an array,
772 and the pretty option otherwise. */
773 if (is_array)
774 pretty = options->prettyformat_arrays;
775 else
776 {
777 if (options->prettyformat == Val_prettyformat)
778 pretty = 1;
779 else
780 pretty = options->prettyformat_structs;
781 }
782
783 done_flag = 0;
784 for (i = 0; i < options->print_max; ++i)
785 {
786 SCM scm_name, v_scm;
787 SCM item = itscm_safe_call_next_x (iter, gdbscm_memory_error_p);
788
789 if (gdbscm_is_exception (item))
790 {
791 ppscm_print_exception_unless_memory_error (item, stream);
792 break;
793 }
794 if (itscm_is_end_of_iteration (item))
795 {
796 /* Set a flag so we can know whether we printed all the
797 available elements. */
798 done_flag = 1;
799 break;
800 }
801
802 if (! scm_is_pair (item))
803 {
804 ppscm_print_pp_type_error
805 (_("result of pretty-printer children iterator is not a pair"
806 " or (end-of-iteration)"),
807 item);
808 continue;
809 }
810 scm_name = scm_car (item);
811 v_scm = scm_cdr (item);
812 if (!scm_is_string (scm_name))
813 {
814 ppscm_print_pp_type_error
815 (_("first element of pretty-printer children iterator is not"
816 " a string"), item);
817 continue;
818 }
819 gdb::unique_xmalloc_ptr<char> name
820 = gdbscm_scm_to_c_string (scm_name);
821
822 /* Print initial "{". For other elements, there are three cases:
823 1. Maps. Print a "," after each value element.
824 2. Arrays. Always print a ",".
825 3. Other. Always print a ",". */
826 if (i == 0)
827 {
828 if (printed_nothing)
829 fputs_filtered ("{", stream);
830 else
831 fputs_filtered (" = {", stream);
832 }
833
834 else if (! is_map || i % 2 == 0)
835 fputs_filtered (pretty ? "," : ", ", stream);
836
837 /* In summary mode, we just want to print "= {...}" if there is
838 a value. */
839 if (options->summary)
840 {
841 /* This increment tricks the post-loop logic to print what
842 we want. */
843 ++i;
844 /* Likewise. */
845 pretty = 0;
846 break;
847 }
848
849 if (! is_map || i % 2 == 0)
850 {
851 if (pretty)
852 {
853 fputs_filtered ("\n", stream);
854 print_spaces_filtered (2 + 2 * recurse, stream);
855 }
856 else
857 wrap_here (n_spaces (2 + 2 *recurse));
858 }
859
860 if (is_map && i % 2 == 0)
861 fputs_filtered ("[", stream);
862 else if (is_array)
863 {
864 /* We print the index, not whatever the child method
865 returned as the name. */
866 if (options->print_array_indexes)
867 fprintf_filtered (stream, "[%d] = ", i);
868 }
869 else if (! is_map)
870 {
871 fputs_filtered (name.get (), stream);
872 fputs_filtered (" = ", stream);
873 }
874
875 if (lsscm_is_lazy_string (v_scm))
876 {
877 struct value_print_options local_opts = *options;
878
879 local_opts.addressprint = 0;
880 lsscm_val_print_lazy_string (v_scm, stream, &local_opts);
881 }
882 else if (scm_is_string (v_scm))
883 {
884 gdb::unique_xmalloc_ptr<char> output
885 = gdbscm_scm_to_c_string (v_scm);
886 fputs_filtered (output.get (), stream);
887 }
888 else
889 {
890 SCM except_scm;
891 struct value *value
892 = vlscm_convert_value_from_scheme (FUNC_NAME, GDBSCM_ARG_NONE,
893 v_scm, &except_scm,
894 gdbarch, language);
895
896 if (value == NULL)
897 {
898 ppscm_print_exception_unless_memory_error (except_scm, stream);
899 break;
900 }
901 common_val_print (value, stream, recurse + 1, options, language);
902 }
903
904 if (is_map && i % 2 == 0)
905 fputs_filtered ("] = ", stream);
906 }
907
908 if (i)
909 {
910 if (!done_flag)
911 {
912 if (pretty)
913 {
914 fputs_filtered ("\n", stream);
915 print_spaces_filtered (2 + 2 * recurse, stream);
916 }
917 fputs_filtered ("...", stream);
918 }
919 if (pretty)
920 {
921 fputs_filtered ("\n", stream);
922 print_spaces_filtered (2 * recurse, stream);
923 }
924 fputs_filtered ("}", stream);
925 }
926
927 done:
928 /* Play it safe, make sure ITER doesn't get GC'd. */
929 scm_remember_upto_here_1 (iter);
930 }
931
932 /* This is the extension_language_ops.apply_val_pretty_printer "method". */
933
934 enum ext_lang_rc
935 gdbscm_apply_val_pretty_printer (const struct extension_language_defn *extlang,
936 struct type *type,
937 LONGEST embedded_offset, CORE_ADDR address,
938 struct ui_file *stream, int recurse,
939 struct value *val,
940 const struct value_print_options *options,
941 const struct language_defn *language)
942 {
943 struct gdbarch *gdbarch = get_type_arch (type);
944 SCM exception = SCM_BOOL_F;
945 SCM printer = SCM_BOOL_F;
946 SCM val_obj = SCM_BOOL_F;
947 struct value *value;
948 enum display_hint hint;
949 enum ext_lang_rc result = EXT_LANG_RC_NOP;
950 enum string_repr_result print_result;
951
952 if (value_lazy (val))
953 value_fetch_lazy (val);
954
955 /* No pretty-printer support for unavailable values. */
956 if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
957 return EXT_LANG_RC_NOP;
958
959 if (!gdb_scheme_initialized)
960 return EXT_LANG_RC_NOP;
961
962 /* Instantiate the printer. */
963 value = value_from_component (val, type, embedded_offset);
964
965 val_obj = vlscm_scm_from_value (value);
966 if (gdbscm_is_exception (val_obj))
967 {
968 exception = val_obj;
969 result = EXT_LANG_RC_ERROR;
970 goto done;
971 }
972
973 printer = ppscm_find_pretty_printer (val_obj);
974
975 if (gdbscm_is_exception (printer))
976 {
977 exception = printer;
978 result = EXT_LANG_RC_ERROR;
979 goto done;
980 }
981 if (gdbscm_is_false (printer))
982 {
983 result = EXT_LANG_RC_NOP;
984 goto done;
985 }
986 gdb_assert (ppscm_is_pretty_printer_worker (printer));
987
988 /* If we are printing a map, we want some special formatting. */
989 hint = ppscm_get_display_hint_enum (printer);
990 if (hint == HINT_ERROR)
991 {
992 /* Print the error as an exception for consistency. */
993 SCM hint_scm = ppscm_get_display_hint_scm (printer);
994
995 ppscm_print_pp_type_error ("Invalid display hint", hint_scm);
996 /* Fall through. A bad hint doesn't stop pretty-printing. */
997 hint = HINT_NONE;
998 }
999
1000 /* Print the section. */
1001 print_result = ppscm_print_string_repr (printer, hint, stream, recurse,
1002 options, gdbarch, language);
1003 if (print_result != STRING_REPR_ERROR)
1004 {
1005 ppscm_print_children (printer, hint, stream, recurse, options,
1006 gdbarch, language,
1007 print_result == STRING_REPR_NONE);
1008 }
1009
1010 result = EXT_LANG_RC_OK;
1011
1012 done:
1013 if (gdbscm_is_exception (exception))
1014 ppscm_print_exception_unless_memory_error (exception, stream);
1015 return result;
1016 }
1017 \f
1018 /* Initialize the Scheme pretty-printer code. */
1019
1020 static const scheme_function pretty_printer_functions[] =
1021 {
1022 { "make-pretty-printer", 2, 0, 0,
1023 as_a_scm_t_subr (gdbscm_make_pretty_printer),
1024 "\
1025 Create a <gdb:pretty-printer> object.\n\
1026 \n\
1027 Arguments: name lookup\n\
1028 name: a string naming the matcher\n\
1029 lookup: a procedure:\n\
1030 (pretty-printer <gdb:value>) -> <gdb:pretty-printer-worker> | #f." },
1031
1032 { "pretty-printer?", 1, 0, 0, as_a_scm_t_subr (gdbscm_pretty_printer_p),
1033 "\
1034 Return #t if the object is a <gdb:pretty-printer> object." },
1035
1036 { "pretty-printer-enabled?", 1, 0, 0,
1037 as_a_scm_t_subr (gdbscm_pretty_printer_enabled_p),
1038 "\
1039 Return #t if the pretty-printer is enabled." },
1040
1041 { "set-pretty-printer-enabled!", 2, 0, 0,
1042 as_a_scm_t_subr (gdbscm_set_pretty_printer_enabled_x),
1043 "\
1044 Set the enabled flag of the pretty-printer.\n\
1045 Returns \"unspecified\"." },
1046
1047 { "make-pretty-printer-worker", 3, 0, 0,
1048 as_a_scm_t_subr (gdbscm_make_pretty_printer_worker),
1049 "\
1050 Create a <gdb:pretty-printer-worker> object.\n\
1051 \n\
1052 Arguments: display-hint to-string children\n\
1053 display-hint: either #f or one of \"array\", \"map\", or \"string\"\n\
1054 to-string: a procedure:\n\
1055 (pretty-printer) -> string | #f | <gdb:value>\n\
1056 children: either #f or a procedure:\n\
1057 (pretty-printer) -> <gdb:iterator>" },
1058
1059 { "pretty-printer-worker?", 1, 0, 0,
1060 as_a_scm_t_subr (gdbscm_pretty_printer_worker_p),
1061 "\
1062 Return #t if the object is a <gdb:pretty-printer-worker> object." },
1063
1064 { "pretty-printers", 0, 0, 0, as_a_scm_t_subr (gdbscm_pretty_printers),
1065 "\
1066 Return the list of global pretty-printers." },
1067
1068 { "set-pretty-printers!", 1, 0, 0,
1069 as_a_scm_t_subr (gdbscm_set_pretty_printers_x),
1070 "\
1071 Set the list of global pretty-printers." },
1072
1073 END_FUNCTIONS
1074 };
1075
1076 void
1077 gdbscm_initialize_pretty_printers (void)
1078 {
1079 pretty_printer_smob_tag
1080 = gdbscm_make_smob_type (pretty_printer_smob_name,
1081 sizeof (pretty_printer_smob));
1082 scm_set_smob_print (pretty_printer_smob_tag,
1083 ppscm_print_pretty_printer_smob);
1084
1085 pretty_printer_worker_smob_tag
1086 = gdbscm_make_smob_type (pretty_printer_worker_smob_name,
1087 sizeof (pretty_printer_worker_smob));
1088 scm_set_smob_print (pretty_printer_worker_smob_tag,
1089 ppscm_print_pretty_printer_worker_smob);
1090
1091 gdbscm_define_functions (pretty_printer_functions, 1);
1092
1093 pretty_printer_list = SCM_EOL;
1094
1095 pp_type_error_symbol = scm_from_latin1_symbol ("gdb:pp-type-error");
1096
1097 ppscm_map_string = scm_from_latin1_string ("map");
1098 ppscm_array_string = scm_from_latin1_string ("array");
1099 ppscm_string_string = scm_from_latin1_string ("string");
1100 }