static SCM
lsscm_get_lazy_string_arg_unsafe (SCM self, int arg_pos, const char *func_name)
{
    SCM_ASSERT_TYPE (lsscm_is_lazy_string (self), self, arg_pos, func_name,
                     lazy_string_smob_name);

    return self;
}
static SCM
ppscm_pretty_print_one_value (SCM printer, struct value **out_value,
			      struct gdbarch *gdbarch,
			      const struct language_defn *language)
{
  SCM result = SCM_BOOL_F;

  *out_value = NULL;
  TRY
    {
      int rc;
      pretty_printer_worker_smob *w_smob
	= (pretty_printer_worker_smob *) SCM_SMOB_DATA (printer);

      result = gdbscm_safe_call_1 (w_smob->to_string, printer,
				   gdbscm_memory_error_p);
      if (gdbscm_is_false (result))
	; /* Done.  */
      else if (scm_is_string (result)
	       || lsscm_is_lazy_string (result))
	; /* Done.  */
      else if (vlscm_is_value (result))
	{
	  SCM except_scm;

	  *out_value
	    = vlscm_convert_value_from_scheme (FUNC_NAME, GDBSCM_ARG_NONE,
					       result, &except_scm,
					       gdbarch, language);
	  if (*out_value != NULL)
	    result = SCM_BOOL_T;
	  else
	    result = except_scm;
	}
      else if (gdbscm_is_exception (result))
	; /* Done.  */
      else
	{
	  /* Invalid result from to-string.  */
	  result = ppscm_make_pp_type_error_exception
	    (_("invalid result from pretty-printer to-string"), result);
	}
    }
  CATCH (except, RETURN_MASK_ALL)
    {
    }
  END_CATCH

  return result;
}
static void
ppscm_print_children (SCM printer, enum display_hint hint,
		      struct ui_file *stream, int recurse,
		      const struct value_print_options *options,
		      struct gdbarch *gdbarch,
		      const struct language_defn *language,
		      int printed_nothing)
{
  pretty_printer_worker_smob *w_smob
    = (pretty_printer_worker_smob *) SCM_SMOB_DATA (printer);
  int is_map, is_array, done_flag, pretty;
  unsigned int i;
  SCM children, status;
  SCM iter = SCM_BOOL_F; /* -Wall */
  struct cleanup *cleanups;

  if (gdbscm_is_false (w_smob->children))
    return;
  if (!gdbscm_is_procedure (w_smob->children))
    {
      ppscm_print_pp_type_error
	(_("pretty-printer \"children\" object is not a procedure or #f"),
	 w_smob->children);
      return;
    }

  cleanups = make_cleanup (null_cleanup, NULL);

  /* If we are printing a map or an array, we want special formatting.  */
  is_map = hint == HINT_MAP;
  is_array = hint == HINT_ARRAY;

  children = gdbscm_safe_call_1 (w_smob->children, printer,
				 gdbscm_memory_error_p);
  if (gdbscm_is_exception (children))
    {
      ppscm_print_exception_unless_memory_error (children, stream);
      goto done;
    }
  /* We combine two steps here: get children, make an iterator out of them.
     This simplifies things because there's no language means of creating
     iterators, and it's the printer object that knows how it will want its
     children iterated over.  */
  if (!itscm_is_iterator (children))
    {
      ppscm_print_pp_type_error
	(_("result of pretty-printer \"children\" procedure is not"
	   " a <gdb:iterator> object"), children);
      goto done;
    }
  iter = children;

  /* Use the prettyformat_arrays option if we are printing an array,
     and the pretty option otherwise.  */
  if (is_array)
    pretty = options->prettyformat_arrays;
  else
    {
      if (options->prettyformat == Val_prettyformat)
	pretty = 1;
      else
	pretty = options->prettyformat_structs;
    }

  done_flag = 0;
  for (i = 0; i < options->print_max; ++i)
    {
      int rc;
      SCM scm_name, v_scm;
      char *name;
      SCM item = itscm_safe_call_next_x (iter, gdbscm_memory_error_p);
      struct cleanup *inner_cleanup = make_cleanup (null_cleanup, NULL);

      if (gdbscm_is_exception (item))
	{
	  ppscm_print_exception_unless_memory_error (item, stream);
	  break;
	}
      if (itscm_is_end_of_iteration (item))
	{
	  /* Set a flag so we can know whether we printed all the
	     available elements.  */
	  done_flag = 1;
	  break;
	}

      if (! scm_is_pair (item))
	{
	  ppscm_print_pp_type_error
	    (_("result of pretty-printer children iterator is not a pair"
	       " or (end-of-iteration)"),
	     item);
	  continue;
	}
      scm_name = scm_car (item);
      v_scm = scm_cdr (item);
      if (!scm_is_string (scm_name))
	{
	  ppscm_print_pp_type_error
	    (_("first element of pretty-printer children iterator is not"
	       " a string"), item);
	  continue;
	}
      name = gdbscm_scm_to_c_string (scm_name);
      make_cleanup (xfree, name);

      /* Print initial "{".  For other elements, there are three cases:
	 1. Maps.  Print a "," after each value element.
	 2. Arrays.  Always print a ",".
	 3. Other.  Always print a ",".  */
      if (i == 0)
	{
         if (printed_nothing)
           fputs_filtered ("{", stream);
         else
           fputs_filtered (" = {", stream);
       }

      else if (! is_map || i % 2 == 0)
	fputs_filtered (pretty ? "," : ", ", stream);

      /* In summary mode, we just want to print "= {...}" if there is
	 a value.  */
      if (options->summary)
	{
	  /* This increment tricks the post-loop logic to print what
	     we want.  */
	  ++i;
	  /* Likewise.  */
	  pretty = 0;
	  break;
	}

      if (! is_map || i % 2 == 0)
	{
	  if (pretty)
	    {
	      fputs_filtered ("\n", stream);
	      print_spaces_filtered (2 + 2 * recurse, stream);
	    }
	  else
	    wrap_here (n_spaces (2 + 2 *recurse));
	}

      if (is_map && i % 2 == 0)
	fputs_filtered ("[", stream);
      else if (is_array)
	{
	  /* We print the index, not whatever the child method
	     returned as the name.  */
	  if (options->print_array_indexes)
	    fprintf_filtered (stream, "[%d] = ", i);
	}
      else if (! is_map)
	{
	  fputs_filtered (name, stream);
	  fputs_filtered (" = ", stream);
	}

      if (lsscm_is_lazy_string (v_scm))
	{
	  struct value_print_options local_opts = *options;

	  local_opts.addressprint = 0;
	  lsscm_val_print_lazy_string (v_scm, stream, &local_opts);
	}
      else if (scm_is_string (v_scm))
	{
	  char *output = gdbscm_scm_to_c_string (v_scm);

	  fputs_filtered (output, stream);
	  xfree (output);
	}
      else
	{
	  SCM except_scm;
	  struct value *value
	    = vlscm_convert_value_from_scheme (FUNC_NAME, GDBSCM_ARG_NONE,
					       v_scm, &except_scm,
					       gdbarch, language);

	  if (value == NULL)
	    {
	      ppscm_print_exception_unless_memory_error (except_scm, stream);
	      break;
	    }
	  common_val_print (value, stream, recurse + 1, options, language);
	}

      if (is_map && i % 2 == 0)
	fputs_filtered ("] = ", stream);

      do_cleanups (inner_cleanup);
    }

  if (i)
    {
      if (!done_flag)
	{
	  if (pretty)
	    {
	      fputs_filtered ("\n", stream);
	      print_spaces_filtered (2 + 2 * recurse, stream);
	    }
	  fputs_filtered ("...", stream);
	}
      if (pretty)
	{
	  fputs_filtered ("\n", stream);
	  print_spaces_filtered (2 * recurse, stream);
	}
      fputs_filtered ("}", stream);
    }

 done:
  do_cleanups (cleanups);

  /* Play it safe, make sure ITER doesn't get GC'd.  */
  scm_remember_upto_here_1 (iter);
}
static enum string_repr_result
ppscm_print_string_repr (SCM printer, enum display_hint hint,
			 struct ui_file *stream, int recurse,
			 const struct value_print_options *options,
			 struct gdbarch *gdbarch,
			 const struct language_defn *language)
{
  struct value *replacement = NULL;
  SCM str_scm;
  enum string_repr_result result = STRING_REPR_ERROR;

  str_scm = ppscm_pretty_print_one_value (printer, &replacement,
					  gdbarch, language);
  if (gdbscm_is_false (str_scm))
    {
      result = STRING_REPR_NONE;
    }
  else if (scm_is_eq (str_scm, SCM_BOOL_T))
    {
      struct value_print_options opts = *options;

      gdb_assert (replacement != NULL);
      opts.addressprint = 0;
      common_val_print (replacement, stream, recurse, &opts, language);
      result = STRING_REPR_OK;
    }
  else if (scm_is_string (str_scm))
    {
      struct cleanup *cleanup;
      size_t length;
      char *string
	= gdbscm_scm_to_string (str_scm, &length,
				target_charset (gdbarch), 0 /*!strict*/, NULL);

      cleanup = make_cleanup (xfree, string);
      if (hint == HINT_STRING)
	{
	  struct type *type = builtin_type (gdbarch)->builtin_char;
	  
	  LA_PRINT_STRING (stream, type, (gdb_byte *) string,
			   length, NULL, 0, options);
	}
      else
	{
	  /* Alas scm_to_stringn doesn't nul-terminate the string if we
	     ask for the length.  */
	  size_t i;

	  for (i = 0; i < length; ++i)
	    {
	      if (string[i] == '\0')
		fputs_filtered ("\\000", stream);
	      else
		fputc_filtered (string[i], stream);
	    }
	}
      result = STRING_REPR_OK;
      do_cleanups (cleanup);
    }
  else if (lsscm_is_lazy_string (str_scm))
    {
      struct value_print_options local_opts = *options;

      local_opts.addressprint = 0;
      lsscm_val_print_lazy_string (str_scm, stream, &local_opts);
      result = STRING_REPR_OK;
    }
  else
    {
      gdb_assert (gdbscm_is_exception (str_scm));
      ppscm_print_exception_unless_memory_error (str_scm, stream);
      result = STRING_REPR_ERROR;
    }

  return result;
}
static SCM
gdbscm_lazy_string_p (SCM scm)
{
    return scm_from_bool (lsscm_is_lazy_string (scm));
}