/* Support for printing D values for GDB, the GNU debugger.

   Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "gdbtypes.h"
#include "gdbcore.h"
#include "d-lang.h"
#include "c-lang.h"

/* Assuming that TYPE is a TYPE_CODE_STRUCT, verify that TYPE is
   a dynamic array, and then print its value to STREAM.  Return
   the number of string characters printed, or -1 if TYPE is not
   a dynamic array.  */
static int
dynamic_array_type (struct type *type, const gdb_byte *valaddr,
		    int embedded_offset, CORE_ADDR address,
		    struct ui_file *stream, int recurse,
		    const struct value *val,
		    const struct value_print_options *options)
{
  if (TYPE_NFIELDS (type) == 2
      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
      && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0
      && value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
			   TARGET_CHAR_BIT * TYPE_LENGTH (type)))
    {
      CORE_ADDR addr;
      struct type *elttype;
      struct type *true_type;
      struct type *ptr_type;
      struct value *ival;
      int length;

      length = unpack_field_as_long (type, valaddr + embedded_offset, 0);

      ptr_type = TYPE_FIELD_TYPE (type, 1);
      elttype = check_typedef (TYPE_TARGET_TYPE (ptr_type));
      addr = unpack_pointer (ptr_type,
			     valaddr + TYPE_FIELD_BITPOS (type, 1) / 8
			     + embedded_offset);
      true_type = check_typedef (elttype);

      true_type = lookup_array_range_type (true_type, 0, length - 1);
      ival = value_at (true_type, addr);

      return d_val_print (true_type,
			  value_contents_for_printing (ival),
			  value_embedded_offset (ival), addr,
			  stream, recurse + 1, ival, options);
    }
  return -1;
}

/* Implements the la_val_print routine for language D.  */
int
d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
             CORE_ADDR address, struct ui_file *stream, int recurse,
	     const struct value *val,
             const struct value_print_options *options)
{
  int ret;

  CHECK_TYPEDEF (type);
  switch (TYPE_CODE (type))
    {
      case TYPE_CODE_STRUCT:
        ret = dynamic_array_type (type, valaddr, embedded_offset, address,
				  stream, recurse, val, options);
	if (ret != -1)
	   break;
      default:
	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
			   recurse, val, options);
    }

  return ret;
}
