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

   Copyright (C) 2008-2016 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 zero if
   TYPE is a dynamic array, non-zero otherwise.  */

static int
dynamic_array_type (struct type *type, const gdb_byte *valaddr,
		    LONGEST 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_any_optimized_out (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);
      true_type = value_type (ival);

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

/* Implements the la_val_print routine for language D.  */
void
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;

  type = 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 == 0)
	  break;
      default:
	c_val_print (type, valaddr, embedded_offset, address, stream,
		     recurse, val, options);
    }
}
