xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/guile/scm-pretty-print.c (revision 99e23f81b2b10aef1a10b03588663e472627bb76)
1 /* GDB/Scheme pretty-printing.
2 
3    Copyright (C) 2008-2017 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 
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 
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 
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 
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   char *msg = xstrprintf ("%s: ~S", message);
331   struct cleanup *cleanup = make_cleanup (xfree, msg);
332   SCM exception
333     = gdbscm_make_error (pp_type_error_symbol,
334 			 NULL /* func */, msg,
335 			 scm_list_1 (object), scm_list_1 (object));
336 
337   do_cleanups (cleanup);
338 
339   return exception;
340 }
341 
342 /* Print MESSAGE as an exception (meaning it is controlled by
343    "guile print-stack").
344    Called from the printer code when the Scheme code returns an invalid type
345    for something.  */
346 
347 static void
348 ppscm_print_pp_type_error (const char *message, SCM object)
349 {
350   SCM exception = ppscm_make_pp_type_error_exception (message, object);
351 
352   gdbscm_print_gdb_exception (SCM_BOOL_F, exception);
353 }
354 
355 /* Helper function for find_pretty_printer which iterates over a list,
356    calls each function and inspects output.  This will return a
357    <gdb:pretty-printer> object if one recognizes VALUE.  If no printer is
358    found, it will return #f.  On error, it will return a <gdb:exception>
359    object.
360 
361    Note: This has to be efficient and careful.
362    We don't want to excessively slow down printing of values, but any kind of
363    random crud can appear in the pretty-printer list, and we can't crash
364    because of it.  */
365 
366 static SCM
367 ppscm_search_pp_list (SCM list, SCM value)
368 {
369   SCM orig_list = list;
370 
371   if (scm_is_null (list))
372     return SCM_BOOL_F;
373   if (gdbscm_is_false (scm_list_p (list))) /* scm_is_pair? */
374     {
375       return ppscm_make_pp_type_error_exception
376 	(_("pretty-printer list is not a list"), list);
377     }
378 
379   for ( ; scm_is_pair (list); list = scm_cdr (list))
380     {
381       SCM matcher = scm_car (list);
382       SCM worker;
383       pretty_printer_smob *pp_smob;
384       int rc;
385 
386       if (!ppscm_is_pretty_printer (matcher))
387 	{
388 	  return ppscm_make_pp_type_error_exception
389 	    (_("pretty-printer list contains non-pretty-printer object"),
390 	     matcher);
391 	}
392 
393       pp_smob = (pretty_printer_smob *) SCM_SMOB_DATA (matcher);
394 
395       /* Skip if disabled.  */
396       if (gdbscm_is_false (pp_smob->enabled))
397 	continue;
398 
399       if (!gdbscm_is_procedure (pp_smob->lookup))
400 	{
401 	  return ppscm_make_pp_type_error_exception
402 	    (_("invalid lookup object in pretty-printer matcher"),
403 	     pp_smob->lookup);
404 	}
405 
406       worker = gdbscm_safe_call_2 (pp_smob->lookup, matcher,
407 				   value, gdbscm_memory_error_p);
408       if (!gdbscm_is_false (worker))
409 	{
410 	  if (gdbscm_is_exception (worker))
411 	    return worker;
412 	  if (ppscm_is_pretty_printer_worker (worker))
413 	    return worker;
414 	  return ppscm_make_pp_type_error_exception
415 	    (_("invalid result from pretty-printer lookup"), worker);
416 	}
417     }
418 
419   if (!scm_is_null (list))
420     {
421       return ppscm_make_pp_type_error_exception
422 	(_("pretty-printer list is not a list"), orig_list);
423     }
424 
425   return SCM_BOOL_F;
426 }
427 
428 /* Subroutine of find_pretty_printer to simplify it.
429    Look for a pretty-printer to print VALUE in all objfiles.
430    If there's an error an exception smob is returned.
431    The result is #f, if no pretty-printer was found.
432    Otherwise the result is the pretty-printer smob.  */
433 
434 static SCM
435 ppscm_find_pretty_printer_from_objfiles (SCM value)
436 {
437   struct objfile *objfile;
438 
439   ALL_OBJFILES (objfile)
440   {
441     objfile_smob *o_smob = ofscm_objfile_smob_from_objfile (objfile);
442     SCM pp = ppscm_search_pp_list (ofscm_objfile_smob_pretty_printers (o_smob),
443 				   value);
444 
445     /* Note: This will return if pp is a <gdb:exception> object,
446        which is what we want.  */
447     if (gdbscm_is_true (pp))
448       return pp;
449   }
450 
451   return SCM_BOOL_F;
452 }
453 
454 /* Subroutine of find_pretty_printer to simplify it.
455    Look for a pretty-printer to print VALUE in the current program space.
456    If there's an error an exception smob is returned.
457    The result is #f, if no pretty-printer was found.
458    Otherwise the result is the pretty-printer smob.  */
459 
460 static SCM
461 ppscm_find_pretty_printer_from_progspace (SCM value)
462 {
463   pspace_smob *p_smob = psscm_pspace_smob_from_pspace (current_program_space);
464   SCM pp
465     = ppscm_search_pp_list (psscm_pspace_smob_pretty_printers (p_smob), value);
466 
467   return pp;
468 }
469 
470 /* Subroutine of find_pretty_printer to simplify it.
471    Look for a pretty-printer to print VALUE in the gdb module.
472    If there's an error a Scheme exception is returned.
473    The result is #f, if no pretty-printer was found.
474    Otherwise the result is the pretty-printer smob.  */
475 
476 static SCM
477 ppscm_find_pretty_printer_from_gdb (SCM value)
478 {
479   SCM pp = ppscm_search_pp_list (pretty_printer_list, value);
480 
481   return pp;
482 }
483 
484 /* Find the pretty-printing constructor function for VALUE.  If no
485    pretty-printer exists, return #f.  If one exists, return the
486    gdb:pretty-printer smob that implements it.  On error, an exception smob
487    is returned.
488 
489    Note: In the end it may be better to call out to Scheme once, and then
490    do all of the lookup from Scheme.  TBD.  */
491 
492 static SCM
493 ppscm_find_pretty_printer (SCM value)
494 {
495   SCM pp;
496 
497   /* Look at the pretty-printer list for each objfile
498      in the current program-space.  */
499   pp = ppscm_find_pretty_printer_from_objfiles (value);
500   /* Note: This will return if function is a <gdb:exception> object,
501      which is what we want.  */
502   if (gdbscm_is_true (pp))
503     return pp;
504 
505   /* Look at the pretty-printer list for the current program-space.  */
506   pp = ppscm_find_pretty_printer_from_progspace (value);
507   /* Note: This will return if function is a <gdb:exception> object,
508      which is what we want.  */
509   if (gdbscm_is_true (pp))
510     return pp;
511 
512   /* Look at the pretty-printer list in the gdb module.  */
513   pp = ppscm_find_pretty_printer_from_gdb (value);
514   return pp;
515 }
516 
517 /* Pretty-print a single value, via the PRINTER, which must be a
518    <gdb:pretty-printer-worker> object.
519    The caller is responsible for ensuring PRINTER is valid.
520    If the function returns a string, an SCM containing the string
521    is returned.  If the function returns #f that means the pretty
522    printer returned #f as a value.  Otherwise, if the function returns a
523    <gdb:value> object, *OUT_VALUE is set to the value and #t is returned.
524    It is an error if the printer returns #t.
525    On error, an exception smob is returned.  */
526 
527 static SCM
528 ppscm_pretty_print_one_value (SCM printer, struct value **out_value,
529 			      struct gdbarch *gdbarch,
530 			      const struct language_defn *language)
531 {
532   SCM result = SCM_BOOL_F;
533 
534   *out_value = NULL;
535   TRY
536     {
537       int rc;
538       pretty_printer_worker_smob *w_smob
539 	= (pretty_printer_worker_smob *) SCM_SMOB_DATA (printer);
540 
541       result = gdbscm_safe_call_1 (w_smob->to_string, printer,
542 				   gdbscm_memory_error_p);
543       if (gdbscm_is_false (result))
544 	; /* Done.  */
545       else if (scm_is_string (result)
546 	       || lsscm_is_lazy_string (result))
547 	; /* Done.  */
548       else if (vlscm_is_value (result))
549 	{
550 	  SCM except_scm;
551 
552 	  *out_value
553 	    = vlscm_convert_value_from_scheme (FUNC_NAME, GDBSCM_ARG_NONE,
554 					       result, &except_scm,
555 					       gdbarch, language);
556 	  if (*out_value != NULL)
557 	    result = SCM_BOOL_T;
558 	  else
559 	    result = except_scm;
560 	}
561       else if (gdbscm_is_exception (result))
562 	; /* Done.  */
563       else
564 	{
565 	  /* Invalid result from to-string.  */
566 	  result = ppscm_make_pp_type_error_exception
567 	    (_("invalid result from pretty-printer to-string"), result);
568 	}
569     }
570   CATCH (except, RETURN_MASK_ALL)
571     {
572     }
573   END_CATCH
574 
575   return result;
576 }
577 
578 /* Return the display hint for PRINTER as a Scheme object.
579    The caller is responsible for ensuring PRINTER is a
580    <gdb:pretty-printer-worker> object.  */
581 
582 static SCM
583 ppscm_get_display_hint_scm (SCM printer)
584 {
585   pretty_printer_worker_smob *w_smob
586     = (pretty_printer_worker_smob *) SCM_SMOB_DATA (printer);
587 
588   return w_smob->display_hint;
589 }
590 
591 /* Return the display hint for the pretty-printer PRINTER.
592    The caller is responsible for ensuring PRINTER is a
593    <gdb:pretty-printer-worker> object.
594    Returns the display hint or #f if the hint is not a string.  */
595 
596 static enum display_hint
597 ppscm_get_display_hint_enum (SCM printer)
598 {
599   SCM hint = ppscm_get_display_hint_scm (printer);
600 
601   if (gdbscm_is_false (hint))
602     return HINT_NONE;
603   if (scm_is_string (hint))
604     {
605       if (gdbscm_is_true (scm_string_equal_p (hint, ppscm_array_string)))
606 	return HINT_STRING;
607       if (gdbscm_is_true (scm_string_equal_p (hint, ppscm_map_string)))
608 	return HINT_STRING;
609       if (gdbscm_is_true (scm_string_equal_p (hint, ppscm_string_string)))
610 	return HINT_STRING;
611       return HINT_ERROR;
612     }
613   return HINT_ERROR;
614 }
615 
616 /* A wrapper for gdbscm_print_gdb_exception that ignores memory errors.
617    EXCEPTION is a <gdb:exception> object.  */
618 
619 static void
620 ppscm_print_exception_unless_memory_error (SCM exception,
621 					   struct ui_file *stream)
622 {
623   if (gdbscm_memory_error_p (gdbscm_exception_key (exception)))
624     {
625       char *msg = gdbscm_exception_message_to_string (exception);
626       struct cleanup *cleanup = make_cleanup (xfree, msg);
627 
628       /* This "shouldn't happen", but play it safe.  */
629       if (msg == NULL || *msg == '\0')
630 	fprintf_filtered (stream, _("<error reading variable>"));
631       else
632 	{
633 	  /* Remove the trailing newline.  We could instead call a special
634 	     routine for printing memory error messages, but this is easy
635 	     enough for now.  */
636 	  size_t len = strlen (msg);
637 
638 	  if (msg[len - 1] == '\n')
639 	    msg[len - 1] = '\0';
640 	  fprintf_filtered (stream, _("<error reading variable: %s>"), msg);
641 	}
642 
643       do_cleanups (cleanup);
644     }
645   else
646     gdbscm_print_gdb_exception (SCM_BOOL_F, exception);
647 }
648 
649 /* Helper for gdbscm_apply_val_pretty_printer which calls to_string and
650    formats the result.  */
651 
652 static enum string_repr_result
653 ppscm_print_string_repr (SCM printer, enum display_hint hint,
654 			 struct ui_file *stream, int recurse,
655 			 const struct value_print_options *options,
656 			 struct gdbarch *gdbarch,
657 			 const struct language_defn *language)
658 {
659   struct value *replacement = NULL;
660   SCM str_scm;
661   enum string_repr_result result = STRING_REPR_ERROR;
662 
663   str_scm = ppscm_pretty_print_one_value (printer, &replacement,
664 					  gdbarch, language);
665   if (gdbscm_is_false (str_scm))
666     {
667       result = STRING_REPR_NONE;
668     }
669   else if (scm_is_eq (str_scm, SCM_BOOL_T))
670     {
671       struct value_print_options opts = *options;
672 
673       gdb_assert (replacement != NULL);
674       opts.addressprint = 0;
675       common_val_print (replacement, stream, recurse, &opts, language);
676       result = STRING_REPR_OK;
677     }
678   else if (scm_is_string (str_scm))
679     {
680       struct cleanup *cleanup;
681       size_t length;
682       char *string
683 	= gdbscm_scm_to_string (str_scm, &length,
684 				target_charset (gdbarch), 0 /*!strict*/, NULL);
685 
686       cleanup = make_cleanup (xfree, string);
687       if (hint == HINT_STRING)
688 	{
689 	  struct type *type = builtin_type (gdbarch)->builtin_char;
690 
691 	  LA_PRINT_STRING (stream, type, (gdb_byte *) string,
692 			   length, NULL, 0, options);
693 	}
694       else
695 	{
696 	  /* Alas scm_to_stringn doesn't nul-terminate the string if we
697 	     ask for the length.  */
698 	  size_t i;
699 
700 	  for (i = 0; i < length; ++i)
701 	    {
702 	      if (string[i] == '\0')
703 		fputs_filtered ("\\000", stream);
704 	      else
705 		fputc_filtered (string[i], stream);
706 	    }
707 	}
708       result = STRING_REPR_OK;
709       do_cleanups (cleanup);
710     }
711   else if (lsscm_is_lazy_string (str_scm))
712     {
713       struct value_print_options local_opts = *options;
714 
715       local_opts.addressprint = 0;
716       lsscm_val_print_lazy_string (str_scm, stream, &local_opts);
717       result = STRING_REPR_OK;
718     }
719   else
720     {
721       gdb_assert (gdbscm_is_exception (str_scm));
722       ppscm_print_exception_unless_memory_error (str_scm, stream);
723       result = STRING_REPR_ERROR;
724     }
725 
726   return result;
727 }
728 
729 /* Helper for gdbscm_apply_val_pretty_printer that formats children of the
730    printer, if any exist.
731    The caller is responsible for ensuring PRINTER is a printer smob.
732    If PRINTED_NOTHING is true, then nothing has been printed by to_string,
733    and format output accordingly. */
734 
735 static void
736 ppscm_print_children (SCM printer, enum display_hint hint,
737 		      struct ui_file *stream, int recurse,
738 		      const struct value_print_options *options,
739 		      struct gdbarch *gdbarch,
740 		      const struct language_defn *language,
741 		      int printed_nothing)
742 {
743   pretty_printer_worker_smob *w_smob
744     = (pretty_printer_worker_smob *) SCM_SMOB_DATA (printer);
745   int is_map, is_array, done_flag, pretty;
746   unsigned int i;
747   SCM children, status;
748   SCM iter = SCM_BOOL_F; /* -Wall */
749   struct cleanup *cleanups;
750 
751   if (gdbscm_is_false (w_smob->children))
752     return;
753   if (!gdbscm_is_procedure (w_smob->children))
754     {
755       ppscm_print_pp_type_error
756 	(_("pretty-printer \"children\" object is not a procedure or #f"),
757 	 w_smob->children);
758       return;
759     }
760 
761   cleanups = make_cleanup (null_cleanup, NULL);
762 
763   /* If we are printing a map or an array, we want special formatting.  */
764   is_map = hint == HINT_MAP;
765   is_array = hint == HINT_ARRAY;
766 
767   children = gdbscm_safe_call_1 (w_smob->children, printer,
768 				 gdbscm_memory_error_p);
769   if (gdbscm_is_exception (children))
770     {
771       ppscm_print_exception_unless_memory_error (children, stream);
772       goto done;
773     }
774   /* We combine two steps here: get children, make an iterator out of them.
775      This simplifies things because there's no language means of creating
776      iterators, and it's the printer object that knows how it will want its
777      children iterated over.  */
778   if (!itscm_is_iterator (children))
779     {
780       ppscm_print_pp_type_error
781 	(_("result of pretty-printer \"children\" procedure is not"
782 	   " a <gdb:iterator> object"), children);
783       goto done;
784     }
785   iter = children;
786 
787   /* Use the prettyformat_arrays option if we are printing an array,
788      and the pretty option otherwise.  */
789   if (is_array)
790     pretty = options->prettyformat_arrays;
791   else
792     {
793       if (options->prettyformat == Val_prettyformat)
794 	pretty = 1;
795       else
796 	pretty = options->prettyformat_structs;
797     }
798 
799   done_flag = 0;
800   for (i = 0; i < options->print_max; ++i)
801     {
802       int rc;
803       SCM scm_name, v_scm;
804       char *name;
805       SCM item = itscm_safe_call_next_x (iter, gdbscm_memory_error_p);
806       struct cleanup *inner_cleanup = make_cleanup (null_cleanup, NULL);
807 
808       if (gdbscm_is_exception (item))
809 	{
810 	  ppscm_print_exception_unless_memory_error (item, stream);
811 	  break;
812 	}
813       if (itscm_is_end_of_iteration (item))
814 	{
815 	  /* Set a flag so we can know whether we printed all the
816 	     available elements.  */
817 	  done_flag = 1;
818 	  break;
819 	}
820 
821       if (! scm_is_pair (item))
822 	{
823 	  ppscm_print_pp_type_error
824 	    (_("result of pretty-printer children iterator is not a pair"
825 	       " or (end-of-iteration)"),
826 	     item);
827 	  continue;
828 	}
829       scm_name = scm_car (item);
830       v_scm = scm_cdr (item);
831       if (!scm_is_string (scm_name))
832 	{
833 	  ppscm_print_pp_type_error
834 	    (_("first element of pretty-printer children iterator is not"
835 	       " a string"), item);
836 	  continue;
837 	}
838       name = gdbscm_scm_to_c_string (scm_name);
839       make_cleanup (xfree, name);
840 
841       /* Print initial "{".  For other elements, there are three cases:
842 	 1. Maps.  Print a "," after each value element.
843 	 2. Arrays.  Always print a ",".
844 	 3. Other.  Always print a ",".  */
845       if (i == 0)
846 	{
847          if (printed_nothing)
848            fputs_filtered ("{", stream);
849          else
850            fputs_filtered (" = {", stream);
851        }
852 
853       else if (! is_map || i % 2 == 0)
854 	fputs_filtered (pretty ? "," : ", ", stream);
855 
856       /* In summary mode, we just want to print "= {...}" if there is
857 	 a value.  */
858       if (options->summary)
859 	{
860 	  /* This increment tricks the post-loop logic to print what
861 	     we want.  */
862 	  ++i;
863 	  /* Likewise.  */
864 	  pretty = 0;
865 	  break;
866 	}
867 
868       if (! is_map || i % 2 == 0)
869 	{
870 	  if (pretty)
871 	    {
872 	      fputs_filtered ("\n", stream);
873 	      print_spaces_filtered (2 + 2 * recurse, stream);
874 	    }
875 	  else
876 	    wrap_here (n_spaces (2 + 2 *recurse));
877 	}
878 
879       if (is_map && i % 2 == 0)
880 	fputs_filtered ("[", stream);
881       else if (is_array)
882 	{
883 	  /* We print the index, not whatever the child method
884 	     returned as the name.  */
885 	  if (options->print_array_indexes)
886 	    fprintf_filtered (stream, "[%d] = ", i);
887 	}
888       else if (! is_map)
889 	{
890 	  fputs_filtered (name, stream);
891 	  fputs_filtered (" = ", stream);
892 	}
893 
894       if (lsscm_is_lazy_string (v_scm))
895 	{
896 	  struct value_print_options local_opts = *options;
897 
898 	  local_opts.addressprint = 0;
899 	  lsscm_val_print_lazy_string (v_scm, stream, &local_opts);
900 	}
901       else if (scm_is_string (v_scm))
902 	{
903 	  char *output = gdbscm_scm_to_c_string (v_scm);
904 
905 	  fputs_filtered (output, stream);
906 	  xfree (output);
907 	}
908       else
909 	{
910 	  SCM except_scm;
911 	  struct value *value
912 	    = vlscm_convert_value_from_scheme (FUNC_NAME, GDBSCM_ARG_NONE,
913 					       v_scm, &except_scm,
914 					       gdbarch, language);
915 
916 	  if (value == NULL)
917 	    {
918 	      ppscm_print_exception_unless_memory_error (except_scm, stream);
919 	      break;
920 	    }
921 	  common_val_print (value, stream, recurse + 1, options, language);
922 	}
923 
924       if (is_map && i % 2 == 0)
925 	fputs_filtered ("] = ", stream);
926 
927       do_cleanups (inner_cleanup);
928     }
929 
930   if (i)
931     {
932       if (!done_flag)
933 	{
934 	  if (pretty)
935 	    {
936 	      fputs_filtered ("\n", stream);
937 	      print_spaces_filtered (2 + 2 * recurse, stream);
938 	    }
939 	  fputs_filtered ("...", stream);
940 	}
941       if (pretty)
942 	{
943 	  fputs_filtered ("\n", stream);
944 	  print_spaces_filtered (2 * recurse, stream);
945 	}
946       fputs_filtered ("}", stream);
947     }
948 
949  done:
950   do_cleanups (cleanups);
951 
952   /* Play it safe, make sure ITER doesn't get GC'd.  */
953   scm_remember_upto_here_1 (iter);
954 }
955 
956 /* This is the extension_language_ops.apply_val_pretty_printer "method".  */
957 
958 enum ext_lang_rc
959 gdbscm_apply_val_pretty_printer (const struct extension_language_defn *extlang,
960 				 struct type *type,
961 				 LONGEST embedded_offset, CORE_ADDR address,
962 				 struct ui_file *stream, int recurse,
963 				 struct value *val,
964 				 const struct value_print_options *options,
965 				 const struct language_defn *language)
966 {
967   struct gdbarch *gdbarch = get_type_arch (type);
968   SCM exception = SCM_BOOL_F;
969   SCM printer = SCM_BOOL_F;
970   SCM val_obj = SCM_BOOL_F;
971   struct value *value;
972   enum display_hint hint;
973   struct cleanup *cleanups;
974   enum ext_lang_rc result = EXT_LANG_RC_NOP;
975   enum string_repr_result print_result;
976   const gdb_byte *valaddr = value_contents_for_printing (val);
977 
978   /* No pretty-printer support for unavailable values.  */
979   if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
980     return EXT_LANG_RC_NOP;
981 
982   if (!gdb_scheme_initialized)
983     return EXT_LANG_RC_NOP;
984 
985   cleanups = make_cleanup (null_cleanup, NULL);
986 
987   /* Instantiate the printer.  */
988   value = value_from_component (val, type, embedded_offset);
989 
990   val_obj = vlscm_scm_from_value (value);
991   if (gdbscm_is_exception (val_obj))
992     {
993       exception = val_obj;
994       result = EXT_LANG_RC_ERROR;
995       goto done;
996     }
997 
998   printer = ppscm_find_pretty_printer (val_obj);
999 
1000   if (gdbscm_is_exception (printer))
1001     {
1002       exception = printer;
1003       result = EXT_LANG_RC_ERROR;
1004       goto done;
1005     }
1006   if (gdbscm_is_false (printer))
1007     {
1008       result = EXT_LANG_RC_NOP;
1009       goto done;
1010     }
1011   gdb_assert (ppscm_is_pretty_printer_worker (printer));
1012 
1013   /* If we are printing a map, we want some special formatting.  */
1014   hint = ppscm_get_display_hint_enum (printer);
1015   if (hint == HINT_ERROR)
1016     {
1017       /* Print the error as an exception for consistency.  */
1018       SCM hint_scm = ppscm_get_display_hint_scm (printer);
1019 
1020       ppscm_print_pp_type_error ("Invalid display hint", hint_scm);
1021       /* Fall through.  A bad hint doesn't stop pretty-printing.  */
1022       hint = HINT_NONE;
1023     }
1024 
1025   /* Print the section.  */
1026   print_result = ppscm_print_string_repr (printer, hint, stream, recurse,
1027 					  options, gdbarch, language);
1028   if (print_result != STRING_REPR_ERROR)
1029     {
1030       ppscm_print_children (printer, hint, stream, recurse, options,
1031 			    gdbarch, language,
1032 			    print_result == STRING_REPR_NONE);
1033     }
1034 
1035   result = EXT_LANG_RC_OK;
1036 
1037  done:
1038   if (gdbscm_is_exception (exception))
1039     ppscm_print_exception_unless_memory_error (exception, stream);
1040   do_cleanups (cleanups);
1041   return result;
1042 }
1043 
1044 /* Initialize the Scheme pretty-printer code.  */
1045 
1046 static const scheme_function pretty_printer_functions[] =
1047 {
1048   { "make-pretty-printer", 2, 0, 0,
1049     as_a_scm_t_subr (gdbscm_make_pretty_printer),
1050     "\
1051 Create a <gdb:pretty-printer> object.\n\
1052 \n\
1053   Arguments: name lookup\n\
1054     name:   a string naming the matcher\n\
1055     lookup: a procedure:\n\
1056       (pretty-printer <gdb:value>) -> <gdb:pretty-printer-worker> | #f." },
1057 
1058   { "pretty-printer?", 1, 0, 0, as_a_scm_t_subr (gdbscm_pretty_printer_p),
1059     "\
1060 Return #t if the object is a <gdb:pretty-printer> object." },
1061 
1062   { "pretty-printer-enabled?", 1, 0, 0,
1063     as_a_scm_t_subr (gdbscm_pretty_printer_enabled_p),
1064     "\
1065 Return #t if the pretty-printer is enabled." },
1066 
1067   { "set-pretty-printer-enabled!", 2, 0, 0,
1068     as_a_scm_t_subr (gdbscm_set_pretty_printer_enabled_x),
1069     "\
1070 Set the enabled flag of the pretty-printer.\n\
1071 Returns \"unspecified\"." },
1072 
1073   { "make-pretty-printer-worker", 3, 0, 0,
1074     as_a_scm_t_subr (gdbscm_make_pretty_printer_worker),
1075     "\
1076 Create a <gdb:pretty-printer-worker> object.\n\
1077 \n\
1078   Arguments: display-hint to-string children\n\
1079     display-hint: either #f or one of \"array\", \"map\", or \"string\"\n\
1080     to-string:    a procedure:\n\
1081       (pretty-printer) -> string | #f | <gdb:value>\n\
1082     children:     either #f or a procedure:\n\
1083       (pretty-printer) -> <gdb:iterator>" },
1084 
1085   { "pretty-printer-worker?", 1, 0, 0,
1086     as_a_scm_t_subr (gdbscm_pretty_printer_worker_p),
1087     "\
1088 Return #t if the object is a <gdb:pretty-printer-worker> object." },
1089 
1090   { "pretty-printers", 0, 0, 0, as_a_scm_t_subr (gdbscm_pretty_printers),
1091     "\
1092 Return the list of global pretty-printers." },
1093 
1094   { "set-pretty-printers!", 1, 0, 0,
1095     as_a_scm_t_subr (gdbscm_set_pretty_printers_x),
1096     "\
1097 Set the list of global pretty-printers." },
1098 
1099   END_FUNCTIONS
1100 };
1101 
1102 void
1103 gdbscm_initialize_pretty_printers (void)
1104 {
1105   pretty_printer_smob_tag
1106     = gdbscm_make_smob_type (pretty_printer_smob_name,
1107 			     sizeof (pretty_printer_smob));
1108   scm_set_smob_print (pretty_printer_smob_tag,
1109 		      ppscm_print_pretty_printer_smob);
1110 
1111   pretty_printer_worker_smob_tag
1112     = gdbscm_make_smob_type (pretty_printer_worker_smob_name,
1113 			     sizeof (pretty_printer_worker_smob));
1114   scm_set_smob_print (pretty_printer_worker_smob_tag,
1115 		      ppscm_print_pretty_printer_worker_smob);
1116 
1117   gdbscm_define_functions (pretty_printer_functions, 1);
1118 
1119   pretty_printer_list = SCM_EOL;
1120 
1121   pp_type_error_symbol = scm_from_latin1_symbol ("gdb:pp-type-error");
1122 
1123   ppscm_map_string = scm_from_latin1_string ("map");
1124   ppscm_array_string = scm_from_latin1_string ("array");
1125   ppscm_string_string = scm_from_latin1_string ("string");
1126 }
1127