dmp-tree.c   [plain text]


/* APPLE LOCAL new tree dump */
/* Common condensed tree display routines.
   Copyright (C) 2001, 2002  Free Software Foundation, Inc.
   Contributed by Ira L. Ruben (ira@apple.com)

This file is part of GNU CC.

GNU CC 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 2, or (at your option)
any later version.

GNU CC 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 GNU CC; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */

/* This dumper is intended for used with the debugger.  You call
   dump_tree(x), where x is the node of interest.  The tree display
   produced here is much more condensed than what is produced by,
   say, debug_tree().  Here each node is displayed as a single
   (possibly line wrapped) line.  The emphasis here is mainly on
   the parse (front-end) trees as opposed to RTL-related info.
 
   Here's an example of some of it's output:
   
   compound_stmt:0xED4D0C line=74 0xED4D20
    scope_stmt:0xED4D20 line=75 BEGIN block=0xED0300
     block:0xED0300 vars=0xECD620 abs-orig=0x0 super=0xED0340 sub=0x0
      var_decl:0xECD620 t=0xEA5310 {int} initial=0xED0260 line=75 comm
                        cntxt=0xECD3F0 sz=32(4) zzz
       integer_cst:0xED0260 t=0xEA5310 {int} 0xFFFFFF9C = -100

     decl_stmt:0xED4D84 line=75 var_decl=0xECD620 {int} zzz

     expr_stmt:0xED4E24 line=76 0xED02E0
      modify_expr:0xED02E0 t=0xEA5310 {int} 0xECD540 0xED4DFC
       var_decl:0xECD540 t=0xEA5310 {int} cntxt=0xECD3F0 i
       nop_expr:0xED4DFC t=0xEA5310 {int} 0xED02C0
        plus_expr:0xED02C0 t=0xEA8540 {long unsigned int} 0xED4DE8 0xED02A0
         nop_expr:0xED4DE8 t=0xEA8540 {long unsigned int} 0xED0280
          trunc_div_expr:0xED0280 t=0xEA5310 {int} 0xECD540 0xECD620
           var_decl:0xECD540 t=0xEA5310 {int} cntxt=0xECD3F0 i
           var_decl:0xECD620 t=0xEA5310 {int} cntxt=0xECD3F0 zzz
         call_expr:0xED02A0 t=0xEA8540 {long unsigned int} func=0xED4DAC args=0xED4DD4
          addr_expr:0xED4DAC (func) t=0xECD690 {pointer_type} 0xEB0850
           function_decl:0xEB0850 t=0xEABD90 {long unsigned int} BUILT_IN_NORMAL strlen
          tree_list:0xED4DD4 (args) purpose=0x0 value=0xED4DC0 chain=0x0
           nop_expr:0xED4DC0 (value) t=0xEAB1C0 {pointer_type} 0xECD4D0
            var_decl:0xECD4D0 t=0xEA8CB0 {pointer_type} cntxt=0xECD3F0 lcl
    scope_stmt:0xED4E38 line=77 END block=0xED0300
  
  Each node is limited to a single line (unless it needs to be wrapped).
  All nodes at the same nesting level are displayed at the same indenting
  level.  Each node is handled individually with code appropriate to what
  it needs to display.
  
  Note that unlike debug_tree() the details of the type info are not shown
  in these trees when (as in this example) the initial node passed to
  dmp_tree() is not a type.  It is assumed that you are mainly interested
  in the parse trees and their relationship to one another and don't need
  the display cluttered up with each node's type info (other than it's
  kind and address).
  
  On the other hand you could be interested in the details of a particular
  type.  In that case call dmp_tree() specifying that type's address as
  the initial node.  When that is done a similarly formatted tree is
  output, but now the details of that type and the types it uses are
  shown.  In the above example, 3 lines up from the bottom, there's a
  pointer (which happens to be for a char*).  Here's what
  dmp_tree(0xEAB1C0) produces:
  
  pointer_type:0xEAB1C0 t=0xEAB150 align=32 prec=32 sz=32(4)
   integer_type:0xEAB150 uns const align=8 *this=0xEAB1C0 prec=8 sz=8(1)
                         min/max=0/255 char
 
  Note, the type is fully followed (except for *this which is overkill).
  Also illustrated is how lines are wrapped if too long for the display.
  Here, it's illustrated assuming about a 72-character wrap point to 
  fit in these comments.  In reality, the wrap point is normally the
  terminal width.  But the DMP_TREE_WRAP environment variable can be
  set to the desired width.  If neither the terminal width with nor the
  environment variable can be accessed, or the value is outside the
  range 72 to 512, the width is set to 130.
  
  There are five language-specific routines that which MUST be uniquely
  defined (via the language hooks) for that language to handle language-
  specific attributes for certain kinds of tree nodes:
     
  1. void dump_identifier(FILE *file, tree node, int indent, int before_id);
  
     Called twice for dmp_tree() for an IDENTIFIER_NODE.  The first
     call is after the common info for the node is generated but before
     displaying the identifier (before_id==0) which is always assumed to
     be the last thing on the line.
     
     The second call is done after the id is displayed (before_id!=0).
     This is for displaying any language-specific node information that
     should be preceded by an newline_and_indent() call or a recursive
     call to dump_tree() for nodes which are language specific operands
     to a IDENTIFIER_NODE.
     
  2. void dump_decl(FILE *file, tree node, int indent, int before_id);
     
     Called twice for dmp_tree() for a ..._DECL node.  The first call
     after the common info for the node is generated but before
     displaying the identifier (before_id==0) which is always assumed
     to be the last thing on the line.
     
     The second call is done after the id is displayed (before_id!=0).
     This is for displaying any language-specific node information that
     should be preceded by an newline_and_indent() call or a recursive
     call to dump_tree() for nodes which are language specific operands
     to a ..._DECL node.
    
  3. void dump_type(FILE *file, tree node, int indent, int before_id);
     
     Called twice for dmp_tree() for a ..._TYPE node.  The first call
     after the common info for the node is generated but before
     displaying the identifier (before_id==0) which is always assumed
     to be the last thing on the line.
     
     The second call is done after the id is displayed (before_id!=0).
     This is for displaying any language-specific node information that
     should be preceded by an newline_and_indent() call or a recursive
     call to dump_tree() for nodes which are language specific operands
     to a ..._TYPE node.
  
  4. int dump_blank_line_p(tree previous_node, tree current_node);
   
     Normally a blank line is inserted before each statement node (a 
     statement node is determined by calling statement_code_p()).  This
     makes the display easier to read by keeping each statement grouped
     like a paragraph.  There may, however, be some kinds of statements
     where a blank line isn't desired (e.g., a begin SCOPE_STMT in C).
     Thus dump_blank_line_p() is called to ask if a particular 
     statement should be preceded by a blank line dependent upon the
     node that preceded it.
     
     dump_blank_line_p() is called for each statement passing the
     previous node (not necessarily a statement) and current node (a
     statement node by definition).  It should return 1 if a blank
     line is to be inserted and 0 otherwise.
  
  5. int dump_lineno_p(FILE *file, tree node);
  
     This is called for each node to display file and/or line number
     information for those nodes that have such information.  If it
     is displayed the function should return 1.  If not, 0.
     
     The function generally does not have to handle ..._DECL nodes
     unless there some special handling is reequired.  They are
     handled by print_lineno() (dump_lineno_p()'s caller).
     It is defined to not repeat the filename if it does not
     change from what's in dump_tree_state.curr_file and then
     it only displays the basename (using lbasename()).  The
     format of the display is " line=nbr(basename)" where the
     leading space is included as usual in these displays and
     the parenthesized basename omitted if not needed or is
     the same as before.
*/
  
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "real.h"
#include "c-common.h"
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "langhooks.h"

/* c-common.h defines a macro called RETURN_EXPR.  But we need to use it
   as the enum defined by tree.def.  */
#undef RETURN_EXPR

#define DMP_TREE
#include "dmp-tree.h"

#if defined(HAVE_UNISTD_H) && DMP_TREE_WRAPPED_OUTPUT
#include <sys/ioctl.h>
#endif

#define MIN_LINE_WRAP 	    72		   /* min wrapping column  */
#define MAX_LINE_WRAP 	   512		   /* max wrapping column  */
#define DEFAULT_LINE_WRAP  130		   /* default              */
#define DMP_TREE_LINE_WRAP "DMP_TREE_WRAP" /* environment variable */

/* Notes to myself:

   c-common.c, verify_tree(), c-decl.c, and cp/ptree.c look intersting!
*/

void dump_tree (FILE *file, const char *annotation, tree node, int indent);
void dmp_tree (tree node);

#define HASH_SIZE 37

struct bucket
{
  tree node;
  struct bucket *next;
};

static struct bucket **table;

static tree *type_array = NULL;
#define TYPE_ARRAY_INITIAL_SIZE 20000
#define TYPE_ARRAY_INCR         10000
static int type_array_size = 0;
static int type_array_next = 0;
static int type_array_incr = TYPE_ARRAY_INITIAL_SIZE;

#if DMP_TREE_WRAPPED_OUTPUT
static char curr_line[2 * MAX_LINE_WRAP];
static int prefix_len;
static int line_index;
static int prev_line_was_null;
static int prev_line_was_wrapped;
static int wrap_column;
#ifdef TIOCGWINSZ
static struct winsize winsize;
#endif
#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
static struct ttysize winsize;
#endif
#endif /* DMP_TREE_WRAPPED_OUTPUT */

dump_tree_state_t dump_tree_state = {
  (int)LAST_AND_UNUSED_TREE_CODE,	/* c */
  -1,					/* nesting_depth */
  0, 					/* dump_full_type */
  0, 					/* really_follow */
  0, 					/* doing_parm_decl */
  0, 					/* doing_call_expr */
  NULL, 				/* curr_file */
  0, 					/* no_new_line */
  0, 					/* line_cnt */
  0,					/* doing_tree_list */
  INT_MAX,				/* max_depth */
  DMP_TREE_VISIT_ANY			/* visit_only_once */
};

#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) \
static void print_ ## SYM (FILE *file, const char *annotation, tree node, int indent);
#include "tree.def"
#undef DEFTREECODE

static void init_dump_state PARAMS ((tree node));
static int no_dump_tree_p   PARAMS ((FILE *file, const char *annotation, tree node, int indent));
static void free_hash_table PARAMS ((void));

static lang_dump_tree_p_t lang_dump_tree_p = no_dump_tree_p;

#define CST_VALUE(node, ok)						\
  ((TREE_INT_CST_HIGH (node) == 0) 					\
    ? (ok &= 1, TREE_INT_CST_LOW (node)) 				\
    : ((TREE_INT_CST_HIGH (node) == -1 && TREE_INT_CST_LOW (node) != 0) \
       ? (ok &= 1, -TREE_INT_CST_LOW (node))				\
       : (ok = 0)))



/*-------------------------------------------------------------------*/

static void
init_dump_state (node)
     tree node;
{
  dump_tree_state.dump_full_type  = TYPE_P (node);
  /*dump_tree_state.nesting_depth = 0; */
  dump_tree_state.really_follow   = 1;
  dump_tree_state.doing_parm_decl = 0;
  dump_tree_state.doing_call_expr = 0;
  dump_tree_state.no_new_line	  = 0;
  dump_tree_state.line_cnt	  = 0;
  dump_tree_state.curr_file	  = NULL;
  dump_tree_state.doing_tree_list = 0;
  /*dump_tree_state.max_depth	  = INT_MAX;*/
  /*dump_tree_state.visit_only_once = DMP_TREE_VISIT_ANY;*/
}

/* Always end the current line by writing a '\n'.
   If column > 0 then output column blanks to the next line.
   Increment dump_tree_state.line_cnt to allow callers to
   determine how many lines are output between any pair of
   points.  */
   
void 
newline_and_indent (file, column)
     FILE *file;
     int column;
{
  fputc ('\n', file);
  ++dump_tree_state.line_cnt;
  
  if (column > 0)
    fprintf (file, "%*c", column, ' ');
}

/* Return 1 if node has been previously seen and 0 otherwise.
   If record_it is non-zero then record that the node was
   seen.  */
int 
node_seen (node, record_it)
     tree node;
     int record_it;
{
  int hash;
  struct bucket *b;
  
  hash = ((unsigned long) node) % HASH_SIZE;

  /* If node is in the table, just mention its address.  */

  for (b = table[hash]; b; b = b->next)
    if (b->node == node)
	return 1;
  
  if (record_it)
    {
      b = (struct bucket *) xmalloc (sizeof (struct bucket));
      b->node = node;
      b->next = table[hash];
      table[hash] = b;
    }
    
  return 0;
}

/* Free the hash table used to record visited nodes.  */
static void
free_hash_table()
{
  int hash;
  struct bucket *b, *next;
  
  if (!table)
    return;
  
  for (hash = 0; hash < HASH_SIZE; ++hash)
    {
      b = table[hash];
      while (b)
	{
	  next = b->next;
	  free (b);
	  b = next;
	}
    }
    
  free (table);
  table = NULL;
}


/*-------------------------------------------------------------------*/

void
print_type (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  int newline = 0;
  
#   define PRINT_TYPE_NAME(node) 					\
    if (!newline && TYPE_NAME (node))					\
      {									\
	if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)		\
	  fprintf (file, " %s", IDENTIFIER_POINTER (TYPE_NAME (node)));	\
	else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL		\
		 && DECL_NAME (TYPE_NAME (node)))			\
	  fprintf (file, " %s",						\
		   IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))));	\
        newline = 1;							\
      }
  
  if (TYPE_CONTEXT (node))
    {
      fprintf (file, " cntxt=");
      fprintf (file, HOST_PTR_PRINTF, 
      			HOST_PTR_PRINTF_VALUE (TYPE_CONTEXT (node)));
    }
      
  if (TYPE_NEEDS_CONSTRUCTING (node))
    fputs (" need-ctor", file);
  if (TYPE_PACKED (node))
    fputs (" packed", file);
  if (TREE_THIS_VOLATILE (node))
    fputs (" volatile", file);
  if (TYPE_READONLY (node))
    fputs (" const", file);
  if (TYPE_RESTRICT (node))
    fputs (" restrict", file);
    
  if (TYPE_LANG_FLAG_0 (node)
      || TYPE_LANG_FLAG_1 (node)
      || TYPE_LANG_FLAG_2 (node)
      || TYPE_LANG_FLAG_3 (node)
      || TYPE_LANG_FLAG_4 (node)
      || TYPE_LANG_FLAG_5 (node)
      || TYPE_LANG_FLAG_6 (node))
    {
      fputs (" type-flags=#", file);
      if (TYPE_LANG_FLAG_0 (node))
	fputc ('0', file);
      if (TYPE_LANG_FLAG_1 (node))
	fputc ('1', file);
      if (TYPE_LANG_FLAG_2 (node))
	fputc ('2', file);
      if (TYPE_LANG_FLAG_3 (node))
	fputc ('3', file);
      if (TYPE_LANG_FLAG_4 (node))
	fputc ('4', file);
      if (TYPE_LANG_FLAG_5 (node))
	fputc ('5', file);
      if (TYPE_LANG_FLAG_6 (node))
	fputc ('6', file);
    }
  
  if (TYPE_USER_ALIGN (node))
    fprintf (file, " usr-algn");
  
  fprintf (file, " align=%d", TYPE_ALIGN (node));
  
  if (TYPE_SYMTAB_ADDRESS (node))
    fprintf (file, " symtab=%d", TYPE_SYMTAB_ADDRESS (node));
  
  if (TYPE_ALIAS_SET (node) != -1)
    {
      fprintf (file, " alias-set=");
      fprintf (file, HOST_WIDE_INT_PRINT_DEC, TYPE_ALIAS_SET (node));
    }
  
  if (TYPE_POINTER_TO (node))
    {
      fprintf (file, " *this=");
      fprintf (file, HOST_PTR_PRINTF,
    		HOST_PTR_PRINTF_VALUE (TYPE_POINTER_TO (node)));
    }
  
  if (TYPE_REFERENCE_TO (node))
    {
      fprintf (file, " &this=");
      fprintf (file, HOST_PTR_PRINTF,
    		HOST_PTR_PRINTF_VALUE (TYPE_REFERENCE_TO (node)));
    }
  
  if (TREE_CODE (node) == ARRAY_TYPE || TREE_CODE (node) == SET_TYPE)
    {
      if (TYPE_DOMAIN (node))
	{
	  fprintf (file, " domain=");
	  fprintf (file, HOST_PTR_PRINTF,
			HOST_PTR_PRINTF_VALUE (TYPE_DOMAIN (node)));
	}
    }
  else if (TREE_CODE (node) == ENUMERAL_TYPE)
    {
      if (TYPE_VALUES (node))
	{
	  fprintf (file, " values=");
	  fprintf (file, HOST_PTR_PRINTF,
			HOST_PTR_PRINTF_VALUE (TYPE_VALUES (node)));
	}
    }
  else if (TREE_CODE (node) == VECTOR_TYPE)
    {
      if (TYPE_DEBUG_REPRESENTATION_TYPE (node))
	{
	  fprintf (file, " values=");
	  fprintf (file, HOST_PTR_PRINTF,
			HOST_PTR_PRINTF_VALUE (TYPE_DEBUG_REPRESENTATION_TYPE (node)));
	}
    }
  
  if (TYPE_ATTRIBUTES (node))
    {
      fprintf (file, " attr=");
      fprintf (file, HOST_PTR_PRINTF,
  			HOST_PTR_PRINTF_VALUE (TYPE_ATTRIBUTES (node)));
    }
  
  if (TYPE_PRECISION (node))
    fprintf (file, " prec=%d", TYPE_PRECISION (node));
    
  if (TYPE_MAIN_VARIANT (node) != node)
    {
      fprintf (file, " main-variant=");
      fprintf (file, HOST_PTR_PRINTF,
		    HOST_PTR_PRINTF_VALUE (TYPE_MAIN_VARIANT (node)));
    }
  if (TYPE_NEXT_VARIANT (node))
    {
      fprintf (file, " next-variant=");
      fprintf (file, HOST_PTR_PRINTF,
		    HOST_PTR_PRINTF_VALUE (TYPE_NEXT_VARIANT (node)));
    }
  
  if (TYPE_NAME (node) && TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
      && DECL_ORIGINAL_TYPE (TYPE_NAME (node)))
    { 
      fprintf (file, " orig-type=");
      fprintf (file, HOST_PTR_PRINTF,
		      HOST_PTR_PRINTF_VALUE (DECL_ORIGINAL_TYPE (TYPE_NAME (node))));
    }

  (void)node_seen (node, TRUE);		/* prevent recursion on this node */
  
  (*lang_hooks.dump_type) (file, node, indent, 0);
  
  if (TYPE_SIZE (node) 
      && TREE_CODE (TYPE_SIZE (node)) == INTEGER_CST
      && TYPE_SIZE_UNIT (node)
      && TREE_CODE (TYPE_SIZE_UNIT (node)) == INTEGER_CST)
    {
      fputs (" sz=", file);
      print_integer_constant (file, TYPE_SIZE (node), 0);
      fputs ("(", file);
      print_integer_constant (file, TYPE_SIZE_UNIT (node), 0);
      fputs (")", file);
    }
  else
    {
      PRINT_TYPE_NAME(node);
      dump_tree (file, "(size)", TYPE_SIZE (node), indent + INDENT);
      dump_tree (file, "(unit size)", TYPE_SIZE_UNIT (node), indent + INDENT);
    }
  
  if (INTEGRAL_TYPE_P (node))
    {
      if (!newline &&
          TREE_CODE (TYPE_MIN_VALUE (node)) == INTEGER_CST
      	  && TREE_CODE (TYPE_MAX_VALUE (node)) == INTEGER_CST)
        {
      	  fputs (" min/max=", file);
      	  print_integer_constant (file, TYPE_MIN_VALUE (node), 0);
      	  fputc ('/', file);
      	  print_integer_constant (file, TYPE_MAX_VALUE (node), 0);
        }
      else
        {
	  PRINT_TYPE_NAME(node);
	  dump_tree (file, "(min)", TYPE_MIN_VALUE (node), indent + INDENT);
	  dump_tree (file, "(max)", TYPE_MAX_VALUE (node), indent + INDENT);
        }
    }
    
  PRINT_TYPE_NAME(node);
  
  if (TYPE_ATTRIBUTES (node))
    dump_tree (file, NULL, TYPE_ATTRIBUTES (node), indent + INDENT);
    
  (*lang_hooks.dump_type) (file, node, indent, 1);
  
  if (TREE_CODE (node) == ARRAY_TYPE || TREE_CODE (node) == SET_TYPE)
    {
      if (TYPE_DOMAIN (node))
	dump_tree (file, "(domain)", TYPE_DOMAIN (node), indent + INDENT);
    }
  else if (TREE_CODE (node) == ENUMERAL_TYPE)
    {
      if (TYPE_VALUES (node))
  	dump_tree (file, "(values)", TYPE_VALUES (node), indent + INDENT);
    }
  
#if 0
  if (TYPE_MAIN_VARIANT (node) == node)
    {
      tree n = TYPE_MAIN_VARIANT (node);
      dump_tree (file, "(main-variant)", n, indent + INDENT);
      for (n = TYPE_NEXT_VARIANT (n); n; n = TYPE_NEXT_VARIANT (n))
        dump_tree (file, "(next-variant)", n, indent + INDENT);
    }
#endif
  
#if 0
  if (TYPE_POINTER_TO (node))
    dump_tree (file, "(ptr-to-this)", TYPE_POINTER_TO (node), indent + INDENT);
  
  if (TYPE_REFERENCE_TO (node))
    dump_tree (file, "(ref-to-this)", TYPE_REFERENCE_TO (node), indent + INDENT);
#endif
  
  if (TREE_TYPE (node))
    dump_tree (file, NULL, TREE_TYPE (node), indent + INDENT);
    
  /* I THINK SOME BINFO-RELATED MACROS NEED TO BE INVESTIGATED AND PUT HERE...  */
}

void
print_decl (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent ATTRIBUTE_UNUSED;
{
  int newline = 0;
  
  if (!node_seen (node, FALSE))
    {
      if (TREE_SIDE_EFFECTS (node) || TREE_THIS_VOLATILE (node))
      	fputs (" volatile", file);
      if (DECL_IGNORED_P (node))
	fputs (" ignored", file);
      if (DECL_ABSTRACT (node))
	fputs (" abst", file);
      if (DECL_IN_SYSTEM_HEADER (node))
	fputs (" in-sys-hdr", file);
      if (DECL_COMMON (node))
	fputs (" comm", file);
      if (DECL_NONLOCAL (node))
	fputs (" nonlcl", file);
#if 0
      if (DECL_ARTIFICIAL (node))
        fputs (" artifical", file);
#endif
      if (DECL_WEAK (node))
        fputs (" weak", file);
      /* APPLE LOCAL begin weak_import (Radar 2809704) --ilr */
      if (DECL_WEAK_IMPORT (node))
	fputs (" weak_import", file);
      /* APPLE LOCAL end weak_import --ilr */
      
      if (DECL_LANG_FLAG_0 (node)
          || DECL_LANG_FLAG_1 (node)
          || DECL_LANG_FLAG_2 (node)
          || DECL_LANG_FLAG_3 (node)
          || DECL_LANG_FLAG_4 (node)
          || DECL_LANG_FLAG_5 (node)
          || DECL_LANG_FLAG_6 (node)
          || DECL_LANG_FLAG_7 (node))
        {
      	  fputs (" lang-flags=#", file);
	  if (DECL_LANG_FLAG_0 (node))
	    fputc ('0', file);
	  if (DECL_LANG_FLAG_1 (node))
	    fputc ('1', file);
	  if (DECL_LANG_FLAG_2 (node))
	    fputc ('2', file);
	  if (DECL_LANG_FLAG_3 (node))
	    fputc ('3', file);
	  if (DECL_LANG_FLAG_4 (node))
	    fputc ('4', file);
	  if (DECL_LANG_FLAG_5 (node))
	    fputc ('5', file);
	  if (DECL_LANG_FLAG_6 (node))
	    fputc ('6', file);
	  if (DECL_LANG_FLAG_7 (node))
	    fputc ('7', file);
        }
  }
  
  if (DECL_ATTRIBUTES (node))
    {
      fprintf (file, " attr=");
      fprintf (file, HOST_PTR_PRINTF,
  			HOST_PTR_PRINTF_VALUE (DECL_ATTRIBUTES (node)));
    }
  
  if (DECL_CONTEXT (node))
    {
      fprintf (file, " cntxt=");
      fprintf (file, HOST_PTR_PRINTF,
		      HOST_PTR_PRINTF_VALUE (DECL_CONTEXT (node)));
    }
  
  if (DECL_RTL_SET_P (node))
    {
      fprintf (file, " rtl=");
      fprintf (file, HOST_PTR_PRINTF,
		      HOST_PTR_PRINTF_VALUE (DECL_RTL (node)));
    }
    
  (*lang_hooks.dump_decl) (file, node, indent, 0);
 
  if (!node_seen (node, TRUE))	/* mark ..._DECL node seen b4 recursing */
    {
      if (TREE_CODE (node) == FIELD_DECL)
        {
          if (DECL_BIT_FIELD_TYPE (node))
            {
              tree bf_type = DECL_BIT_FIELD_TYPE (node);
	      fprintf (file, " bf-type=");
	      fprintf (file, HOST_PTR_PRINTF,
		       HOST_PTR_PRINTF_VALUE (bf_type));
	      if (TYPE_NAME (bf_type))
		{
		  if (TREE_CODE (TYPE_NAME (bf_type)) == IDENTIFIER_NODE)
		    {
		      if (IDENTIFIER_POINTER (TYPE_NAME (bf_type))
			  && *IDENTIFIER_POINTER (TYPE_NAME (bf_type)))
		      fprintf (file, " {%s}", IDENTIFIER_POINTER (TYPE_NAME (bf_type)));
		    }
		  else if (TREE_CODE (TYPE_NAME (bf_type)) == TYPE_DECL
			   && DECL_NAME (TYPE_NAME (bf_type))
			   && IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (bf_type)))
			   && *IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (bf_type))))
		    fprintf (file, " {%s}",
			     IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (bf_type))));
		}
	      else
		fprintf (file, " {%s}", tree_code_name[(int)TREE_CODE (bf_type)]);
	    }
	    
	  if (DECL_FIELD_OFFSET (node) && DECL_FIELD_BIT_OFFSET (node))
	    {
	      if (TREE_CODE (DECL_FIELD_OFFSET (node)) == INTEGER_CST
		  && TREE_CODE (DECL_FIELD_BIT_OFFSET (node)) == INTEGER_CST)
		{
		  fputs (" off=", file);
		  print_integer_constant (file, DECL_FIELD_BIT_OFFSET (node), 0);
		  fputs ("(", file);
		  print_integer_constant (file, DECL_FIELD_OFFSET (node), 0);
		  fputs (")", file);
		}
	      else
		{
		  if (DECL_NAME (node))
		    fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
		  dump_tree (file, "(offset)", DECL_FIELD_OFFSET (node),
			     indent + INDENT);
		  dump_tree (file, "(bit offset)", DECL_FIELD_BIT_OFFSET (node),
			     indent + INDENT);
		  newline = 1;
		}
	    }
	  else 
	    {
	      if (DECL_FIELD_OFFSET (node))
	        {
	          if (TREE_CODE (DECL_FIELD_OFFSET (node)) == INTEGER_CST)
	            {
		      fputs (" off=", file);
		      print_integer_constant (file, DECL_FIELD_BIT_OFFSET (node), 0);
		    }
		  else
		    {
		      if (DECL_NAME (node))
			fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
		      dump_tree (file, "(offset)", DECL_FIELD_OFFSET (node),
				 indent + INDENT);
		      newline = 1;
		    }
	        }
	      if (DECL_FIELD_BIT_OFFSET (node))
	        {
	          if (!newline
	              && TREE_CODE (DECL_FIELD_BIT_OFFSET (node)) == INTEGER_CST)
	            {
		      fputs (" bit-off=", file);
		      print_integer_constant (file, DECL_FIELD_BIT_OFFSET (node), 0);
		    }
		  else
		    {
		      if (!newline && DECL_NAME (node))
			fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
		      dump_tree (file, "(bit offset)", DECL_FIELD_BIT_OFFSET (node),
				 indent + INDENT);
		      newline = 1;
		    }
	        }
	    }
        }
      
      if (!newline && DECL_SIZE (node) && DECL_SIZE_UNIT (node)
          && TREE_CODE (DECL_SIZE (node)) == INTEGER_CST
          && TREE_CODE (DECL_SIZE_UNIT (node)) == INTEGER_CST)
	{
	  fputs (" sz=", file);
	  print_integer_constant (file, DECL_SIZE (node), 0);
	  fputs ("(", file);
	  print_integer_constant (file, DECL_SIZE_UNIT (node), 0);
	  fputs (")", file);
        }
      else
        {
	  if (!newline && DECL_NAME (node))
	    fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
	  newline = 1;
     	  dump_tree (file, "(size)", DECL_SIZE (node), indent + INDENT);
      	  dump_tree (file, "(unit size)", DECL_SIZE_UNIT (node), indent + INDENT);
        }
    }
  
  if (!newline && DECL_NAME (node))
    fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
  
  (*lang_hooks.dump_decl) (file, node, indent, 1);
}

void
print_ref (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent ATTRIBUTE_UNUSED;
{
  if (TREE_THIS_VOLATILE (node))
    fputs (" volatile", file);
  if (TREE_READONLY (node))
    fputs (" readonly", file);
}

#define MAX_COMMENT 50

/* The "..." arguments are a list of zero or more strings with a NULL
   as the last list item.  They are used to annotate each respective
   operand.  The annotation convention is that if an string is not
   enclosed in parentheses it will annotation it's operand display. If
   it is enclosed in parentheses it will be appended to the kind:address
   display.  Examples:
   
      annotation kind:address ....
  or
      kind:address (annotation) ....
*/
      
void 
print_operands VPARAMS ((FILE *file, tree node, int indent, int follow, ...))
{
#ifndef ANSI_PROTOTYPES
  FILE *file;
  tree node;
  int indent, follow;
#endif
  int i, first_rtl, len, len1, nomore, maxlen;
  va_list ap;
  char *s, temp[MAX_COMMENT + 2];
  
  VA_START (ap, follow);
#ifndef ANSI_PROTOTYPES
  file = va_arg (ap, FILE *);
  node = va_arg (ap, tree);
  indent = va_arg (ap, int);
  follow = va_arg (ap, int);
#endif
  
  len = TREE_CODE_LENGTH (TREE_CODE (node));
  first_rtl = first_rtl_op (TREE_CODE (node));
    
  for (i = nomore = maxlen = 0; i < len && i < first_rtl; ++i)
    {
      s = nomore ? NULL : va_arg (ap, char *);
      if (s == NULL)
	{
	  nomore = 1;
      	  fprintf (file, " ");
	  fprintf (file, HOST_PTR_PRINTF,	
      	  		HOST_PTR_PRINTF_VALUE (TREE_OPERAND (node, i)));
	}
      else
        {
          if (s[0] != '(')
            {
	      len1 = strlen (s);
	      if (len1 > maxlen)
		maxlen = len1;
            }
          else
            {
              s = strcpy (temp, ++s);
              temp[strlen (temp) - 1] = '\0';
            }
	  fprintf (file, " %s=", s);
	  fprintf (file, HOST_PTR_PRINTF,
	  			HOST_PTR_PRINTF_VALUE (TREE_OPERAND (node, i)));
	}
    }
  
  va_end (ap);
  
  if (first_rtl < len)
    {
      for (i = first_rtl; i < len; ++i)
        if (TREE_OPERAND (node, i))
          break;
      if (i < len)
        {
	  fputs (" [rtl=", file);
	  for (i = first_rtl; i < len; ++i)
	    {
	      if (i > first_rtl)
		fputc (',', file);
	      fprintf (file, HOST_PTR_PRINTF,
			    HOST_PTR_PRINTF_VALUE (TREE_OPERAND (node, i)));
	    }
	  fputc (']', file);
      }
    }
    
  if (follow && dump_tree_state.really_follow)
    {
      maxlen = MIN (maxlen, MAX_COMMENT);
      temp[maxlen] = '\0';
      
      /* Reusing the arg list -- does this work when !ANSI_PROTOTYPES?  */
      VA_START (ap, follow);
#     ifndef ANSI_PROTOTYPES
      file = va_arg (ap, FILE *);
      node = va_arg (ap, tree);
      indent = va_arg (ap, int);
#     endif
      
      for (i = nomore = 0; i < len && i < first_rtl; ++i)
	{
	  s = nomore ? NULL : va_arg (ap, char *);
	  if (s == NULL)
	    {
	      nomore = 1;
	      if (maxlen > 0)
	        s = memset(temp, ' ', maxlen);
	    }
	  else if (s[0] != '(')
	    {
	      len = strlen (s);
	      if (maxlen < len)
		  len = maxlen;
	      if (len < maxlen)
		{
		  memset(temp, ' ', maxlen);
		  s = memcpy(temp + maxlen - len - 1, s, len);
		}
	    }
	  dump_tree (file, s, TREE_OPERAND (node, i), indent + INDENT);
	}
      
      va_end (ap);
    }
}

void
print_lineno (file, node)
     FILE *file;
     tree node;
{
  if (!(*lang_hooks.dump_lineno_p) (file, node)
      && TREE_CODE_CLASS (TREE_CODE (node)) == 'd')
    {
      if (TREE_CODE (node) != FUNCTION_DECL || !DECL_BUILT_IN (node))
        {
	  if (dump_tree_state.curr_file
	      && strcmp(dump_tree_state.curr_file, DECL_SOURCE_FILE (node)) == 0)
	    fprintf (file, " line=%d", DECL_SOURCE_LINE (node));
	  else
	    {
	      dump_tree_state.curr_file = (char *)DECL_SOURCE_FILE (node);
	      fprintf (file, " line=%d(%s)", DECL_SOURCE_LINE (node),
			      lbasename(DECL_SOURCE_FILE (node)));
	  }
	}
    }
}

void 
print_integer_constant (file, node, hex)
     FILE *file;
     tree node;
     int hex;
{
  int ok = 1;
  tree type = TREE_TYPE (node);
  int size;
  
  size  = (TREE_CODE_CLASS (TREE_CODE (type)) == 't') ? 
           CST_VALUE (TYPE_SIZE_UNIT (type), ok)
    	   : 4; /*CST_VALUE (type,ok);*/
  if (!ok)
    size = 4;
  
  if (hex)
    {
      if (TREE_INT_CST_HIGH (node) == 0
	  || (TREE_INT_CST_HIGH (node) == -1 && TREE_INT_CST_LOW (node) != 0))
	{
	  if (size == 1)
	    fprintf (file, "0x%.2lX = ", (unsigned long)(TREE_INT_CST_LOW (node) & 0xFF));
	  else if (size == 2)
	    fprintf (file, "0x%.4lX = ", (unsigned long)(TREE_INT_CST_LOW (node) & 0xFFFF));
	  else if (size == 4)
	    fprintf (file, "0x%.8lX = ", (unsigned long)TREE_INT_CST_LOW (node));
	  else
	    fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
		     TREE_INT_CST_HIGH (node), TREE_INT_CST_LOW (node));
	}
    }
    
  if (TREE_INT_CST_HIGH (node) == 0)
    fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, TREE_INT_CST_LOW (node));
  else if (TREE_INT_CST_HIGH (node) == -1 && TREE_INT_CST_LOW (node) != 0)
    {
      fputs ("-", file);
      fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, -TREE_INT_CST_LOW (node));
    }
  else
    fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
	     TREE_INT_CST_HIGH (node), TREE_INT_CST_LOW (node));
}

void
print_real_constant (file, node)
     FILE *file;
     tree node;
{
  char string[100];
  real_to_decimal (string, &TREE_REAL_CST (node), sizeof (string), 0, 1);
  fputs (string, file);
}

void 
print_string_constant (file, str, maxlen)
     FILE *file;
     const char *str;
     int maxlen;
{
  char c, buf[1024+12+1], *s;
  int  i = 0, len;
  
  if (!str)
    {
      fputs ("(null)", file);
      return;
    }
  
  /* Buffer string so that we write it with a single fputs().  This is
     required for our line wrapping code to know when it is "inside"
     a string.  */
     
  len = strlen (str);
  if (len > 1021)
    len = 1021;
  
  s    = buf;
  *s++ = '"';
  
  while ((c = *str++) != '\0')
    {
      if (c == '\b') {
	*s++ =  '\\'; *s++ = 'b'; i += 2;
      } else if (c == '\f') {
	*s++ =  '\\'; *s++ = 'f'; i += 2;
      } else if (c == '\v') {
	*s++ =  '\\'; *s++ = 'v'; i += 2;
      } else if (c == '\r') {
	*s++ =  '\\'; *s++ = 'r'; i += 2;
      } else if (c == '\n') {
	*s++ =  '\\'; *s++ = 'n'; i += 2;
      } else if (c == '\t') {
	*s++ =  '\\'; *s++ = 't'; i += 2;
      } else if (!isprint (c)) {
	s += sprintf (s, "\\%03o", c); i += 4;
      } else {
	*s++ = c; ++i;
      }
      if (i > maxlen && len > maxlen + 12)
        {
          strcpy (s, "...(more)...");
          break;
        }
    }
  *s++ = '"';
  *s   = '\0';
  fputs (buf, file);
}

void
print_tree_flags (file, node)
     FILE *file;
     tree node;
{
  if (TREE_SIDE_EFFECTS (node))
    fputs ("side-effects", file);
  if (TREE_CONSTANT (node))
    fputs (" const", file);
  if (TREE_ADDRESSABLE (node))
    fputs (" addressable", file);
  if (TREE_THIS_VOLATILE (node))
    fputs (" volatile", file);
  if (TREE_READONLY (node))
    fputs (" readonly", file);
  if (TREE_UNSIGNED (node))
    fputs (" uns", file);
  if (TREE_ASM_WRITTEN (node))
    fputs (" asm-written", file);
  if (TREE_USED (node))
    fputs (" used", file);
  if (TREE_NOTHROW (node))
    fputs (" nothrow", file);
  if (TREE_STATIC (node))
    fputs (" static", file);
  if (TREE_PUBLIC (node))
    fputs (" public", file);
  if (TREE_PRIVATE (node))
    fputs (" private", file);
  if (TREE_PROTECTED (node))
    fputs (" protected", file);
  if (TREE_BOUNDED (node))
    fputs (" bounded", file);
  if (TREE_DEPRECATED (node))
    fputs (" deprecated", file);
  /* APPLE LOCAL begin unavailable (Radar 2809697) --ilr */
  if (TREE_UNAVAILABLE (node))
    fputs (" unavailable", file);
  /* APPLE LOCAL end unavailable --ilr */
 
  if (TREE_LANG_FLAG_0 (node)
      || TREE_LANG_FLAG_1 (node)
      || TREE_LANG_FLAG_2 (node)
      || TREE_LANG_FLAG_3 (node)
      || TREE_LANG_FLAG_4 (node)
      || TREE_LANG_FLAG_5 (node)
      || TREE_LANG_FLAG_6 (node))
    {
      fputs (" tree-flags=#", file);
      if (TREE_LANG_FLAG_0 (node))
	fputc ('0', file);
      if (TREE_LANG_FLAG_1 (node))
	fputc ('1', file);
      if (TREE_LANG_FLAG_2 (node))
	fputc ('2', file);
      if (TREE_LANG_FLAG_3 (node))
	fputc ('3', file);
      if (TREE_LANG_FLAG_4 (node))
	fputc ('4', file);
      if (TREE_LANG_FLAG_5 (node))
	fputc ('5', file);
      if (TREE_LANG_FLAG_6 (node))
	fputc ('6', file);
    }
}

/*-------------------------------------------------------------------*/

/* Just in case print anything set in the common part of this node.  */

static void
print_ERROR_MARK (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent ATTRIBUTE_UNUSED;
{
  if (TREE_CHAIN (node))
    {
      fprintf (file, " chain=");
      fprintf (file, HOST_PTR_PRINTF,
	      HOST_PTR_PRINTF_VALUE (TREE_CHAIN (node)));
    }
  if (TREE_TYPE (node))
    {
      fprintf (file, " type=");
      fprintf (file, HOST_PTR_PRINTF,
	      HOST_PTR_PRINTF_VALUE (TREE_TYPE (node)));
    }
  print_tree_flags (file, node);
}

static void
print_IDENTIFIER_NODE (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  if (TREE_PUBLIC (node))
      fputs (" public", file);
  if (TREE_ADDRESSABLE (node))
    fputs (" addressable", file);
  
  (*lang_hooks.dump_identifier) (file, node, indent, 0);
  fprintf (file, " len=%d %s", 
  		IDENTIFIER_LENGTH (node), IDENTIFIER_POINTER (node));
  (*lang_hooks.dump_identifier) (file, node, indent, 1);
}

static void
print_TREE_LIST (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  if (TREE_VIA_VIRTUAL (node))
    fputs (" via-virt", file);
  if (TREE_VIA_PUBLIC (node))
    fputs (" via-public", file);
  if (TREE_VIA_PRIVATE (node))
    fputs (" via-private", file);
  if (TREE_VIA_PROTECTED (node))
    fputs (" via-protected", file);
  fprintf (file, " purpose=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (TREE_PURPOSE (node)));
  fprintf (file, " value=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (TREE_VALUE (node)));
  fprintf (file, " chain=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (TREE_CHAIN (node)));
  		
  ++dump_tree_state.doing_tree_list;
  (void)node_seen (node, TRUE);
  
  dump_tree (file, "(purpose)", TREE_PURPOSE (node), indent + INDENT);
  dump_tree (file, "(value)", TREE_VALUE (node), indent + INDENT);
  
  for (node = TREE_CHAIN (node); node; node = TREE_CHAIN (node))
    dump_tree (file, annotation, node, indent + 0); /* keep list at same indent */
  
  --dump_tree_state.doing_tree_list;
}

static void
print_TREE_VEC (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  int i, skip_line, len = TREE_VEC_LENGTH (node);
  
  if (TREE_VIA_VIRTUAL (node))
    fputs (" via-virt", file);
  if (TREE_VIA_PUBLIC (node))
    fputs (" via-public", file);
  if (TREE_VIA_PRIVATE (node))
    fputs (" via-private", file);
  if (TREE_VIA_PROTECTED (node))
    fputs (" via-protected", file);
    
  fprintf (file, " len=%d", len);
  
  for (i = skip_line = 0; i < len; ++i)
    if (TREE_VEC_ELT (node, i))
      {
	char temp[MAX_COMMENT + 20];
	
	if (skip_line)
	  newline_and_indent (file, 0);
	skip_line = 1;
	if (annotation)
	  {
	    temp[0] = '(';
	    if (annotation[0] == '(')
	      {
		strcpy (temp+1, annotation+1);
		temp[strlen (temp) - 1] = '\0';
	      }
	    else
	      strcpy (temp+1, annotation);
	    sprintf (temp + strlen (temp), ":%i)", i);
	  }
	else
	    sprintf (temp, "(%i)", i);
	dump_tree (file, temp, TREE_VEC_ELT (node, i), indent + INDENT);
      }
  
  if (len > 1 && indent > 1)
    newline_and_indent (file, 0);
}

static void
print_BLOCK (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent ATTRIBUTE_UNUSED;
{
  tree n;
  
  fprintf (file, " vars=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (BLOCK_VARS (node)));
  fprintf (file, " abs-orig=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (BLOCK_ABSTRACT_ORIGIN (node)));
  fprintf (file, " super=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (BLOCK_SUPERCONTEXT (node)));
  fprintf (file, " sub=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (BLOCK_SUBBLOCKS (node)));
  fprintf (file, " frag-origin=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (BLOCK_FRAGMENT_ORIGIN (node)));
  fprintf (file, " frag-chain=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (BLOCK_FRAGMENT_CHAIN (node)));

  if (BLOCK_HANDLER_BLOCK (node))
      fputs (" handler_block_flag", file);
  if (BLOCK_ABSTRACT (node))
      fputs (" abstract_flag", file);
  
  for (n = BLOCK_VARS (node); n; n = TREE_CHAIN (n))
    if (!node_seen (n, FALSE))
      dump_tree (file, NULL, n, indent + INDENT);
  
#if 0
  for (n = BLOCK_SUBBLOCKS (node); n; n = BLOCK_CHAIN (n))
    if (!node_seen (n))
      dump_tree (file, NULL, n, indent + INDENT);
#endif
  
  /*dump_tree (file, NULL, BLOCK_SUPERCONTEXT (node), indent + INDENT);*/
  
  if (!node_seen (BLOCK_ABSTRACT_ORIGIN (node), FALSE))
    dump_tree (file, NULL, BLOCK_ABSTRACT_ORIGIN (node), indent + INDENT);
}

static void
print_VOID_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_type (file, annotation, node, indent);
}

static void
print_INTEGER_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  if (TYPE_IS_SIZETYPE (node))
    fputs (" sizetype", file);
  if (TREE_UNSIGNED (node))
    fputs (" uns", file);
    
  print_type (file, annotation, node, indent);
}

static void
print_REAL_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_type (file, annotation, node, indent);
}

static void
print_COMPLEX_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_type (file, annotation, node, indent);
}

static void
print_VECTOR_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_type (file, annotation, node, indent);
}

static void
print_ENUMERAL_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  if (TREE_UNSIGNED (node))
    fputs (" uns", file);
    
  print_type (file, annotation, node, indent);
}

static void
print_BOOLEAN_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_type (file, annotation, node, indent);
}

static void
print_CHAR_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_type (file, annotation, node, indent);
}

static void
print_POINTER_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_type (file, annotation, node, indent);
}

static void
print_OFFSET_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  fprintf (file, " basetype=");
  fprintf (file, HOST_PTR_PRINTF,
  			HOST_PTR_PRINTF_VALUE (TYPE_OFFSET_BASETYPE (node)));
  
  print_type (file, annotation, node, indent);
}

static void
print_REFERENCE_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_type (file, annotation, node, indent);
}

static void
print_METHOD_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  tree n;
  
  if (TYPE_METHOD_BASETYPE (node))
    {
      fprintf (file, " basetype=");
      fprintf (file, HOST_PTR_PRINTF,
    			HOST_PTR_PRINTF_VALUE (TYPE_METHOD_BASETYPE (node)));
    }
  fprintf (file, " args=");
  fprintf (file, HOST_PTR_PRINTF,
  			HOST_PTR_PRINTF_VALUE (TYPE_ARG_TYPES (node)));
  
  print_type (file, annotation, node, indent);
  
  for (n = TYPE_ARG_TYPES (node); n; n = TREE_CHAIN (n))
    dump_tree (file, "(args)", n, indent + INDENT);
}

static void
print_FILE_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_type (file, annotation, node, indent);
}

static void
print_ARRAY_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  if (TYPE_STRING_FLAG (node))
    fputs (" string-flag", file);
  if (TYPE_NONALIASED_COMPONENT (node))
    fputs (" nonaliased-component", file);
    
  print_type (file, annotation, node, indent);
}

static void
print_SET_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  if (TYPE_STRING_FLAG (node))
    fputs (" string-flag", file);

  print_type (file, annotation, node, indent);
}

static void
print_RECORD_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  tree n;
  
  if (TYPE_NO_FORCE_BLK (node))
    fputs (" no-force-blk", file);
  fprintf (file, " fields=");
  fprintf (file, HOST_PTR_PRINTF,
  			HOST_PTR_PRINTF_VALUE (TYPE_FIELDS (node)));
    
  print_type (file, annotation, node, indent);
  (void)node_seen (node, TRUE);
    
  for (n = TYPE_FIELDS (node); n; n = TREE_CHAIN (n))
    dump_tree (file, NULL, n, indent + INDENT);
}

static void
print_UNION_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  if (TYPE_NO_FORCE_BLK (node))
    fputs (" no-force-blk", file);
  if (TYPE_TRANSPARENT_UNION (node))
    fputs (" transparent-union", file);
  fprintf (file, " fields=");
  fprintf (file, HOST_PTR_PRINTF,
  			HOST_PTR_PRINTF_VALUE (TYPE_FIELDS (node)));
    
  print_type (file, annotation, node, indent);
  (void)node_seen (node, TRUE);
    
  for (node = TYPE_FIELDS (node); node; node = TREE_CHAIN (node))
    dump_tree (file, NULL, node, indent + INDENT);
}

static void
print_QUAL_UNION_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{  
  if (TYPE_NO_FORCE_BLK (node))
    fputs (" no-force-blk", file);
  fprintf (file, " fields=");
  fprintf (file, HOST_PTR_PRINTF,
  				HOST_PTR_PRINTF_VALUE (TYPE_FIELDS (node)));
    
  print_type (file, annotation, node, indent);
  (void)node_seen (node, TRUE);
  
  for (node = TYPE_FIELDS (node); node; node = TREE_CHAIN (node))
    dump_tree (file, NULL, node, indent + INDENT);
}

static void
print_FUNCTION_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  tree n;
  
  if (TYPE_METHOD_BASETYPE (node))
    {
      fprintf (file, " basetype=");
      fprintf (file, HOST_PTR_PRINTF,
    			HOST_PTR_PRINTF_VALUE (TYPE_METHOD_BASETYPE (node)));
    }
    
  if (TYPE_RETURNS_STACK_DEPRESSED (node))
    fputs (" ret-stk-depressed", file);
  if (TYPE_AMBIENT_BOUNDEDNESS (node))
    fputs (" ambient-boundedness", file);
  fprintf (file, " args=");
  fprintf (file, HOST_PTR_PRINTF,
  			HOST_PTR_PRINTF_VALUE (TYPE_ARG_TYPES (node)));
  
  print_type (file, annotation, node, indent);
  (void)node_seen (node, TRUE);
    
  for (n = TYPE_ARG_TYPES (node); n; n = TREE_CHAIN (n))
    dump_tree (file, "(args)", n, indent + INDENT);
}

static void
print_LANG_TYPE (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_type (file, annotation, node, indent);
}

static void
print_INTEGER_CST (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent ATTRIBUTE_UNUSED;
{
  print_tree_flags (file, node);
  fputc (' ', file);
  print_integer_constant (file, node, 1);
}

static void
print_REAL_CST (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent ATTRIBUTE_UNUSED;
{
  print_tree_flags (file, node);
  fputc (' ', file);
  print_real_constant (file, node);
}

static void
print_COMPLEX_CST (file, annotation, node, indent)
     FILE *file ATTRIBUTE_UNUSED;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_tree_flags (file, node);
  fprintf (file, " real=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (TREE_REALPART (node)));
  fprintf (file, " imag=");
  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (TREE_IMAGPART (node)));
  
  dump_tree (file, "(real)", TREE_REALPART (node), indent + INDENT);
  dump_tree (file, "(imag)", TREE_IMAGPART (node), indent + INDENT);
}

static void
print_VECTOR_CST (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  tree n, type = TREE_TYPE (node); 
  tree t1 = NULL;
  int  i, ok, size = 0;
  int ok2 = 0;
  char *fmt = (char *)"this is just to stop compiler warning";
  
  union {
      unsigned char  uc[16];
      unsigned short us[8];
      unsigned long  ul[4];
  } vec_value;
  
  print_tree_flags (file, node);

  ok = (type && TREE_CODE (type) == VECTOR_TYPE);
  if (ok)
    {
      type = TREE_TYPE (type);
      n    = TYPE_SIZE_UNIT (type);
      size = CST_VALUE (n, ok);
      t1 = TREE_VECTOR_CST_ELTS (node);
     
      if (TREE_CODE (type) == INTEGER_TYPE
	  && (size == 1 || size == 2 || size == 4))
	{
	  fmt = (char *) (TREE_UNSIGNED (type) ? "%u%s" : "%d%s");
	  if (TREE_CODE (TREE_VALUE (t1)) == INTEGER_CST)
	    {
	      vec_value.ul[0] = CST_VALUE (TREE_VALUE (t1), ok);
	      vec_value.ul[1] = CST_VALUE (TREE_VALUE (TREE_CHAIN (t1)), ok);
	      vec_value.ul[2] = CST_VALUE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (t1))), ok);
	      vec_value.ul[3] = CST_VALUE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (t1)))), ok);
	    }
	  ok2 = ok;
	}
      else if (TREE_CODE (type) != REAL_TYPE
	       || TREE_CODE (TREE_VALUE (t1)) != REAL_CST
	       || size != 4)
	ok2 = 0;
      else
	ok2 = ok;
    }
  
  if (ok2)
    {
      fprintf (file, " ");
      fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE(TREE_VALUE (t1)));
      fprintf (file, " ");
      fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE(TREE_VALUE (TREE_CHAIN (t1))));
      fprintf (file, " ");
      fprintf (file, HOST_PTR_PRINTF,
			HOST_PTR_PRINTF_VALUE(TREE_VALUE (TREE_CHAIN (TREE_CHAIN (t1)))));
      fprintf (file, " ");
      fprintf (file, HOST_PTR_PRINTF,
      			HOST_PTR_PRINTF_VALUE(TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (t1))))));
      newline_and_indent (file, indent + INDENT);
      fputc ('(', file);
      
      switch (size)
	{
	case 1:
	  for (i = 0; i < 16; ++i)
	    fprintf (file, fmt, vec_value.uc[i], (i < 15) ? "," : "");
	  break;
	  
	case 2:
	  for (i = 0; i < 8; ++i)
	    fprintf (file, fmt, vec_value.us[i], (i < 7) ? "," : "");
	  break;
	  
	case 4:
	  if (TREE_CODE (type) != REAL_TYPE)
	    for (i = 0; i < 4; ++i)
	      fprintf (file, fmt, vec_value.ul[i], (i < 3) ? "," : "");
	  else
	    {
	      print_real_constant (file, TREE_VALUE (t1));
	      fputc (',', file);
	      print_real_constant (file, TREE_VALUE (TREE_CHAIN (t1)));
	      fputc (',', file);
	      print_real_constant (file, TREE_VALUE (TREE_CHAIN (TREE_CHAIN (t1))));
	      fputc (',', file);
	      print_real_constant (file, TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (t1)))));
	    }
	  break;
	}
	
      fputc (')', file);
    }
  else
    {
      dump_tree (file, NULL, TREE_VALUE (t1), indent + INDENT);
      dump_tree (file, NULL, TREE_VALUE (TREE_CHAIN (t1)), indent + INDENT);
      dump_tree (file, NULL, TREE_VALUE (TREE_CHAIN (TREE_CHAIN (t1))), indent + INDENT);
      dump_tree (file, NULL, TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (t1)))), indent + INDENT);
    }
}

static void
print_STRING_CST (file, annotation, node, indent)
     FILE *file ATTRIBUTE_UNUSED;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node ATTRIBUTE_UNUSED;
     int indent ATTRIBUTE_UNUSED;
{
  print_tree_flags (file, node);
  fprintf (file, " ptr=");
  fprintf (file, HOST_PTR_PRINTF,
  		HOST_PTR_PRINTF_VALUE (TREE_STRING_POINTER (node)));
  fprintf (file, " ");
  print_string_constant (file, (char *)TREE_STRING_POINTER (node), 30);
  
  if (TREE_CHAIN (node))
    {
      fprintf (file, " chain=");
      fprintf (file, HOST_PTR_PRINTF, 
      			HOST_PTR_PRINTF_VALUE (TREE_CHAIN (node)));
  
      for (node = TREE_CHAIN (node); node; node = TREE_CHAIN (node))
    	dump_tree (file, NULL, node, indent + INDENT);
    }
}

static void
print_FUNCTION_DECL (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  tree n;
  
  if (DECL_BUILT_IN (node))
    {
      if (DECL_BUILT_IN_CLASS (node) == BUILT_IN_MD)
	fprintf (file, " BUILT_IN_MD %d", DECL_FUNCTION_CODE (node));
      else
	fprintf (file, " %s",
		 built_in_class_names[(int) DECL_BUILT_IN_CLASS (node)]);
    }
    
  if (DECL_BUILT_IN_NONANSI (node))
    fputs (" builtin-nonansi", file);
  
  if (dump_tree_state.doing_call_expr)
    {
      print_decl (file, annotation, node, indent);
      return;
    }
    
  if (DECL_EXTERNAL (node))
    fputs (" ext", file);
  if (TREE_PUBLIC (node))
    fputs (" pub", file);
  if (TREE_PRIVATE (node))
    fputs (" pvt", file);
  if (TREE_PROTECTED (node))
    fputs (" prot", file);
#if 0
  if (TREE_STATIC (node))
    fputs (" def", file);
  if (TREE_ADDRESSABLE (node))
    fputs (" addrsable", file);
#endif
  if (TREE_ASM_WRITTEN (node))
    fputs (" asm-wrtn", file);
  if (TREE_NOTHROW (node))
    fputs (" nothr", file);

  if (DECL_INLINE (node))
    fputs (" inline", file);
  if (DECL_NO_STATIC_CHAIN (node))
    fputs (" no-static-chain", file);
  if (DECL_VIRTUAL_P (node))
    fputs (" virt", file);
  if (DECL_STATIC_CONSTRUCTOR (node))
    fputs (" static-ctor", file);
  if (DECL_STATIC_DESTRUCTOR (node))
    fputs (" static-dtor", file);
  
  if (DECL_INITIAL (node))
    {
      fprintf (file, " initial=");
      fprintf (file, HOST_PTR_PRINTF,	
			  HOST_PTR_PRINTF_VALUE (DECL_INITIAL (node)));
    }
    
  if (DECL_SAVED_INSNS (node))
    {
      fprintf (file, " saved-insns=");
      fprintf (file, HOST_PTR_PRINTF,
    	     HOST_PTR_PRINTF_VALUE (DECL_SAVED_INSNS (node)));
    }

  if (!DECL_EXTERNAL (node))
    {
      fprintf (file, " ");
      fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (DECL_RESULT (node)));
      fprintf (file, "(");
      fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (DECL_ARGUMENTS (node)));
      fprintf (file, "){");
      fprintf (file, HOST_PTR_PRINTF,
		 HOST_PTR_PRINTF_VALUE (DECL_LANG_SPECIFIC(node)
		 			   ? DECL_SAVED_TREE (node) : 0));
      fprintf (file, "}");
    }    
  print_decl (file, annotation, node, indent);
  
  /*if (DECL_LANG_SPECIFIC(node) && DECL_SAVED_TREE (node)) ?? */
  if (DECL_RESULT (node))
    dump_tree (file, NULL, DECL_RESULT (node), indent + INDENT);
  
  dump_tree_state.doing_parm_decl = 1;
  for (n = DECL_ARGUMENTS (node); n; n = TREE_CHAIN (n))
    dump_tree (file, NULL, n, indent + INDENT);
  dump_tree_state.doing_parm_decl = 0;
  
  if (DECL_LANG_SPECIFIC(node))    /* saftey test, used by DECL_SAVED_TREE */
    for (n = DECL_SAVED_TREE (node); n; n = TREE_CHAIN (n))
      {
	if (n == DECL_SAVED_TREE (node)
	    && TREE_CODE (n) == EXPR_STMT
	    && EXPR_STMT_EXPR (n) == void_zero_node)
	  {
	    dump_tree_state.really_follow = 0;
	    dump_tree (file, "(dummy, to be deleted)", n, indent + INDENT);
	    dump_tree_state.really_follow = 1;
	  }
	else
	  dump_tree (file, NULL, n, indent + INDENT);
      }
      
   /* FIXME: DECL_VINDEX ?? */
}

static void
print_LABEL_DECL (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  if (TREE_ADDRESSABLE (node))
    fputs (" seen", file);
  if (DECL_TOO_LATE (node))
    fputs (" too-late", file);
  if (DECL_ERROR_ISSUED (node))
    fputs (" error-issued", file);
  print_decl (file, annotation, node, indent);
}

static void
print_CONST_DECL (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_decl (file, annotation, node, indent);
}

static void
print_TYPE_DECL (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{  
  if (DECL_ORIGINAL_TYPE (node))
    {
      fprintf (file, " orig_type=");
      fprintf (file, HOST_PTR_PRINTF,
    			HOST_PTR_PRINTF_VALUE (DECL_ORIGINAL_TYPE (node)));
    }
  if (TYPE_DECL_SUPPRESS_DEBUG (node))
    fputs (" suppress-debug", file);
  print_decl (file, annotation, node, indent);
}

static void
print_VAR_DECL (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  if (node_seen (node, FALSE))
    {
      print_decl (file, annotation, node, indent);
      return;
    }
    
  if (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node))
    fputs (" static", file);
  if (TREE_PUBLIC (node))
    fputs (" pub", file);
  if (DECL_EXTERNAL (node))
    fputs (" ext", file);
  if (DECL_REGISTER (node))
   fputs (" regdcl", file);
  if (TREE_CODE (node) == VAR_DECL && DECL_IN_TEXT_SECTION (node))
    fputs (" in-txt-sect", file);
  if (DECL_VIRTUAL_P (node))
    fputs (" virt", file);
  if (DECL_POINTER_ALIAS_SET_KNOWN_P (node))
    {
      fputs (" alias-set=", file);
      fprintf (file, HOST_WIDE_INT_PRINT_DEC, 
	       		DECL_POINTER_ALIAS_SET (node));
    }
  
  if (TREE_CODE (node) == PARM_DECL && DECL_TRANSPARENT_UNION (node))
    fputs (" transp-union", file);
 
  if (TREE_CODE (node) != PARM_DECL)
    {
      fprintf (file, " initial=");
      fprintf (file, HOST_PTR_PRINTF,
      				HOST_PTR_PRINTF_VALUE (DECL_INITIAL (node)));
      print_decl (file, annotation, node, indent);
      dump_tree (file, NULL, DECL_INITIAL (node), indent + INDENT);
    }
  else
    print_decl (file, annotation, node, indent);
}

static void
print_PARM_DECL (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  if (dump_tree_state.doing_parm_decl)
    {
      if (DECL_ARG_TYPE (node))
        {
	  fprintf (file, " arg-type=");
	  fprintf (file, HOST_PTR_PRINTF,
		HOST_PTR_PRINTF_VALUE (DECL_ARG_TYPE (node)));
	}
      if (DECL_ARG_TYPE_AS_WRITTEN (node))
	{
	  fprintf (file, " as-written=");
	  fprintf (file, HOST_PTR_PRINTF,
		HOST_PTR_PRINTF_VALUE (DECL_ARG_TYPE_AS_WRITTEN (node)));
	}
      if (DECL_INCOMING_RTL (node))
	{
      	  fprintf (file, " incoming-rtl=");
	  fprintf (file, HOST_PTR_PRINTF,
      		HOST_PTR_PRINTF_VALUE (DECL_INCOMING_RTL (node)));
	}
    }
  print_VAR_DECL (file, annotation, node, indent);
}

static void
print_RESULT_DECL (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_decl (file, annotation, node, indent);
}

static void
print_FIELD_DECL (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  if (node_seen (node, FALSE))
    {
      print_decl (file, annotation, node, indent);
      return;
    }
    
  if (TREE_ADDRESSABLE (node))
    fputs (" addressable", file);
  if (TREE_READONLY (node))
    fputs (" readonly", file);
  
  if (DECL_VIRTUAL_P (node))
    fputs (" virt", file);
  if (DECL_PACKED (node))
    fputs (" packed", file);
  if (TREE_UNSIGNED (node))
    fputs (" uns", file);
  if (DECL_BIT_FIELD (node))
    fputs (" bitfield", file);
  if (DECL_NONADDRESSABLE_P (node))
    fputs (" nonaddr", file);
  fprintf (file, " off-align=");
  fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED,
	   DECL_OFFSET_ALIGN (node));
  print_decl (file, annotation, node, indent);
}

static void
print_NAMESPACE_DECL (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_decl (file, annotation, node, indent);
}

static void
print_COMPONENT_REF (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_ref (file, annotation, node, indent);
  print_operands (file, node, indent, TRUE, "(struct/union)", "(field)", NULL);
}

static void
print_BIT_FIELD_REF (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_ref (file, annotation, node, indent);
  print_operands (file, node, indent, TRUE, "(struct/union)", "(#bits)", "(pos)", NULL);
}

static void
print_INDIRECT_REF (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_ref (file, annotation, node, indent);
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_BUFFER_REF (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_ref (file, annotation, node, indent);
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_ARRAY_REF (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_ref (file, annotation, node, indent);
  print_operands (file, node, indent, TRUE, "(base)", "(index)", NULL);
}

static void
print_ARRAY_RANGE_REF (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_ref (file, annotation, node, indent);
  print_operands (file, node, indent, TRUE, "(base)", "(index)", NULL);
}

static void
print_VTABLE_REF (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  print_ref (file, annotation, node, indent);
  print_operands (file, node, indent, TRUE, "(base)", "(index)", NULL);
}

static void
print_CONSTRUCTOR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  if (TREE_ADDRESSABLE (node))
    fputs (" must-be-in-mem", file);
  if (TREE_STATIC (node))
    fputs (" static", file);
  if (TREE_CONSTANT (node))
    fputs (" const", file);
  if (TREE_BOUNDED (node))
    fputs (" bounded", file);
  
  print_operands (file, node, indent, FALSE, NULL);
  
  for (node = CONSTRUCTOR_ELTS (node); node; node = TREE_CHAIN (node))
    dump_tree (file, NULL, node, indent + INDENT);
}

static void
print_COMPOUND_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  if (TREE_NO_UNUSED_WARNING (node))
    fputs (" no-unused", file);
  
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_MODIFY_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_INIT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TARGET_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, "(target)", "(init)",
  			"(cleanup)", "(saved-init)", NULL);
}

static void
print_COND_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, "(cond)", "(?)", "(:)", NULL);
}

static void
print_BIND_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, "(vars)", "(body)", "(block)", NULL);
}

static void
print_CALL_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  if (TREE_NOTHROW (node))
    fputs (" nothrow", file);
  
  dump_tree_state.doing_call_expr = 1;
  print_operands (file, node, indent, TRUE, "(func)", "(args)", NULL);
  dump_tree_state.doing_call_expr = 0;
}

static void
print_METHOD_CALL_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, "(self)", "(args)", NULL);
}

static void
print_WITH_CLEANUP_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_CLEANUP_POINT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_PLACEHOLDER_EXPR (file, annotation, node, indent)
     FILE *file ATTRIBUTE_UNUSED;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node ATTRIBUTE_UNUSED;
     int indent ATTRIBUTE_UNUSED;
{
  /*print_operands (file, node, indent, FALSE, NULL);*/
  /* this is an 'x' node, not an expr node */
}

static void
print_WITH_RECORD_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_PLUS_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_MINUS_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_MULT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TRUNC_DIV_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_CEIL_DIV_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_FLOOR_DIV_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_ROUND_DIV_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TRUNC_MOD_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_CEIL_MOD_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_FLOOR_MOD_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_ROUND_MOD_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_RDIV_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_EXACT_DIV_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_FIX_TRUNC_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_FIX_CEIL_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_FIX_FLOOR_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_FIX_ROUND_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_FLOAT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_NEGATE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_MIN_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_MAX_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_ABS_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_FFS_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_LSHIFT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_RSHIFT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_LROTATE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_RROTATE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_BIT_IOR_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_BIT_XOR_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_BIT_AND_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_BIT_ANDTC_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_BIT_NOT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TRUTH_ANDIF_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TRUTH_ORIF_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TRUTH_AND_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TRUTH_OR_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TRUTH_XOR_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TRUTH_NOT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_LT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_LE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_GT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_GE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_EQ_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_NE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_UNORDERED_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_ORDERED_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_UNLT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_UNLE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_UNGT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_UNGE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_UNEQ_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_IN_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_SET_LE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_CARD_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_RANGE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_CONVERT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_NOP_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_NON_LVALUE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_SAVE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_VIEW_CONVERT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_UNSAVE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_RTL_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_ADDR_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_REFERENCE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_ENTRY_VALUE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_FDESC_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_COMPLEX_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_CONJ_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_REALPART_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_IMAGPART_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_PREDECREMENT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_PREINCREMENT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_POSTDECREMENT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_POSTINCREMENT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_VA_ARG_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_TRY_CATCH_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, "(try)", "(catch)", NULL);
}

static void
print_TRY_FINALLY_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_GOTO_SUBROUTINE_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_LABEL_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_GOTO_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_RETURN_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_EXIT_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_LOOP_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_LABELED_BLOCK_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_EXIT_BLOCK_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_EXPR_WITH_FILE_LOCATION (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_SWITCH_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_EXC_PTR_EXPR (file, annotation, node, indent)
     FILE *file;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node;
     int indent;
{
  print_operands (file, node, indent, TRUE, NULL);
}

static void
print_CLZ_EXPR (file, annotation, node, indent)
     FILE *file ATTRIBUTE_UNUSED;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node ATTRIBUTE_UNUSED;
     int indent ATTRIBUTE_UNUSED;
{
  /* TO DO */
}
static void
print_CTZ_EXPR (file, annotation, node, indent)
     FILE *file ATTRIBUTE_UNUSED;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node ATTRIBUTE_UNUSED;
     int indent ATTRIBUTE_UNUSED;
{
  /* TO DO */
}
static void
print_PARITY_EXPR (file, annotation, node, indent)
     FILE *file ATTRIBUTE_UNUSED;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node ATTRIBUTE_UNUSED;
     int indent ATTRIBUTE_UNUSED;
{
  /* TO DO */
}
static void
print_POPCOUNT_EXPR (file, annotation, node, indent)
     FILE *file ATTRIBUTE_UNUSED;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node ATTRIBUTE_UNUSED;
     int indent ATTRIBUTE_UNUSED;
{
  /* TO DO */
}

/*-------------------------------------------------------------------*/

/* Alaways the last lang_dump_tree_p to keep lang_dump_tree_p from being
   NULL.  A return of 0 always forces the tree node switch to go to its
   default case.  */
   
static int 
no_dump_tree_p (file, annotation, node, indent)
     FILE *file ATTRIBUTE_UNUSED;
     const char *annotation ATTRIBUTE_UNUSED;
     tree node ATTRIBUTE_UNUSED;
     int indent ATTRIBUTE_UNUSED;
{
  return 0;
}

/* Language-specific initializers call this to add to the chain of language-
   specific tree node dumpers.  It is expected that their default node case
   will call the function returned from here which was saved during their
   initialization.  */
   
lang_dump_tree_p_t
set_dump_tree_p (new_lang_dump_tree_p)
     lang_dump_tree_p_t new_lang_dump_tree_p;
{
   lang_dump_tree_p_t old_lang_dump_tree_p = lang_dump_tree_p;
   lang_dump_tree_p = new_lang_dump_tree_p;
   return old_lang_dump_tree_p;
}

/* Annotations enclosed in parentheses are appended to the initial
   kind:address display.  Otherwise they prefix it.  Note that a
   prefix annotation is expected to have at least a trailing
   space but a parenthesized annotation should end with it's
   delimiting right parentheses.  */
   
void 
dump_tree (file, annotation, node, indent)
     FILE *file;
     const char *annotation;
     tree node;
     int indent;
{
  int good_node, no_new_line, plen = 0;
  static tree previous_node;
  
  no_new_line = dump_tree_state.no_new_line;
  dump_tree_state.no_new_line = 0;
  
  /* prefix_len contains the length of the fixed part of a tree node
     display line and can be used by tree node dumpers to control
     line wrapping if the line info for that node gets too long.  */
     
  if (node == NULL)
    return;
    
  if (dump_tree_state.nesting_depth < 0)
    {
      /* If not called from dmp_tree3() then create hash table to record
         which nodes we visit.  We still also do this for dmp_tree3()
         but only the first time dmp_tree3() calls this routine.  After
         that it's dmp_tree3() responsibility to free the hash table.  */
      if (dump_tree_state.visit_only_once != DMP_TREE_VISIT_ONCE2)
        {
      	  init_dump_state(node);
      	  table = (struct bucket **) xmalloc (HASH_SIZE * sizeof (struct bucket *));
      	  memset ((char *) table, 0, HASH_SIZE * sizeof (struct bucket *));
      	  if (dump_tree_state.visit_only_once == DMP_TREE_VISIT_ONCE1)
      	    dump_tree_state.visit_only_once = DMP_TREE_VISIT_ONCE2;
      	}
      
      indent = 0;
      previous_node = NULL_TREE;
#if DMP_TREE_WRAPPED_OUTPUT
      {
        char *wrap_str = getenv(DMP_TREE_LINE_WRAP);
	line_index = prev_line_was_null = prev_line_was_wrapped = 0;
	wrap_column = 0;
	if (wrap_str)
	  wrap_column = strtol (wrap_str, NULL, 10);
#if defined(TIOCGSIZE) || defined(TIOCGWINSZ)
	if (wrap_column < MIN_LINE_WRAP || wrap_column > MAX_LINE_WRAP)
	  {
#ifdef TIOCGWINSZ
	    wrap_column = ioctl (fileno(file), TIOCGWINSZ, &winsize);
	    if (wrap_column >= 0)
	      wrap_column = winsize.ws_col;
#endif
#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
	    wrap_column = ioctl (fileno(file), TIOCGSIZE, &winsize);
	    if (wrap_column >= 0)
	      wrap_column = winsize.ts_cols;
#endif
          }
      }
#endif /* TIOCGSIZE || TIOCGWINSZ */
      if (wrap_column < MIN_LINE_WRAP || wrap_column > MAX_LINE_WRAP)
	wrap_column = DEFAULT_LINE_WRAP;
#endif /* DMP_TREE_WRAPPED_OUTPUT */
    }
  
  if (dump_tree_state.visit_only_once != DMP_TREE_VISIT_ANY
      && node_seen (node, TRUE))
    return;
  
  if (dump_tree_state.dump_full_type && node_seen (node, FALSE))
    return;
    
  if (dump_tree_state.doing_tree_list && node_seen (node, FALSE))
    return;
    
  if (dump_tree_state.nesting_depth >= dump_tree_state.max_depth)
    return;
  
  if (dump_tree_state.nesting_depth >= 0)
    {
      if (!no_new_line)
        {
	  newline_and_indent (file, 0);
	  if (statement_code_p (TREE_CODE (node))
	      || (TREE_CODE (node) == TREE_VEC && TREE_VEC_LENGTH (node) > 1))
	    {
	      if (previous_node
		  && TREE_CODE (previous_node) != TREE_CODE (node)
		  && (*lang_hooks.dump_blank_line_p) (previous_node, node))
		newline_and_indent (file, 0);
	    }
      	}
      previous_node = node;
      if (indent > 0)
        fprintf (file, "%*c", indent, ' ');
    }
  
  ++dump_tree_state.nesting_depth;
  
  plen = indent;
  if (annotation && *annotation && *annotation != '(')
    plen += fprintf (file, "%s", annotation);

  good_node = ((int) TREE_CODE (node) < dump_tree_state.max_code);
      
  if (good_node)
    {
      plen += fprintf (file, "%s:", tree_code_name[(int) TREE_CODE (node)]);
      plen += fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (node));
    }
  else
    {
      plen += fprintf (file, "%d (?):", (int) TREE_CODE (node));
      plen += fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (node));
    }

  if (annotation && *annotation == '(')
    plen += fprintf (file, " %s", annotation);
    
  if (good_node)
    {
      if (TREE_CODE_CLASS (TREE_CODE (node)) != 't'
	  && TREE_TYPE (node)
	  && TREE_CODE_CLASS (TREE_CODE (TREE_TYPE (node))) == 't')
	{
	  tree type, type0 = TREE_TYPE (node);
	  
	  if (dump_tree_state.doing_call_expr
	      && TREE_CODE (node) == FUNCTION_DECL && TREE_TYPE (type0))
	    type = TREE_TYPE (type0);
	  else
	    type = type0;
	    
	  fprintf (file, " t=");
	  fprintf (file, HOST_PTR_PRINTF, HOST_PTR_PRINTF_VALUE (type0));
	  
	  if (TYPE_NAME (type))
	    {
	      if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
	        {
	          if (IDENTIFIER_POINTER (TYPE_NAME (type))
	              && *IDENTIFIER_POINTER (TYPE_NAME (type)))
		  fprintf (file, " {%s}", IDENTIFIER_POINTER (TYPE_NAME (type)));
		}
	      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
		       && DECL_NAME (TYPE_NAME (type))
		       && IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))
		       && *IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))))
		fprintf (file, " {%s}",
			 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
	    }
	  else
	    fprintf (file, " {%s}", tree_code_name[(int) TREE_CODE (type)]);
	   
	  /* If doing a full program dump we also want to dump the types too.
	     So dmp_tree3() will do it after we dump all the decls's.  All
	     we do here is record all the decl's types in an array.  We won't
	     worry about dups here.  That is taken care of when we process
	     this array.  */
	     
	  if (dump_tree_state.visit_only_once == DMP_TREE_VISIT_ONCE2
	      && !node_seen (type, FALSE))
	    {
	      if (type_array_next >= type_array_size)
		{
		  type_array_size += type_array_incr;
		  type_array_incr = TYPE_ARRAY_INCR;
		  type_array = (tree *) xrealloc (type_array,
		  				  sizeof (tree) * type_array_size);
		}
  
  		type_array[type_array_next++] = type;
	    }
	}
      else if (dump_tree_state.dump_full_type && TREE_TYPE (node))
	{
	  fprintf (file, " t=");
	  fprintf (file, HOST_PTR_PRINTF,
		   HOST_PTR_PRINTF_VALUE (TREE_TYPE (node)));
	}
    }
  
#if DMP_TREE_WRAPPED_OUTPUT
  prefix_len = plen + 1;  	/* include blank following prefix */
  prev_line_was_wrapped = 0;
#endif

  print_lineno (file, node);	 /* line nbr info where possible */
  
  if (! (*lang_dump_tree_p) (file, annotation, node, indent))
    {
      switch (TREE_CODE (node)) 
        {
#         define DEFTREECODE(SYM, NAME, TYPE, LENGTH) \
        	case SYM: print_ ## SYM (file, annotation, node, indent); break;
#         include "tree.def"
#         undef DEFTREECODE
        default:
          print_ERROR_MARK (file, annotation, node, indent);
          break;
        }
    }
 
  --dump_tree_state.nesting_depth;
    
  if (dump_tree_state.nesting_depth < 0)
    {
      newline_and_indent (file, 0);
      if (dump_tree_state.visit_only_once != DMP_TREE_VISIT_ONCE2)
      	free_hash_table ();
    }
  else
    (void)node_seen (node, TRUE);
    
}

/* Called from debugger to dump the tree for a specific node.  */
void 
dmp_tree (node)
     tree node;
{
  dump_tree_state.max_depth = INT_MAX;
  dump_tree_state.visit_only_once = DMP_TREE_VISIT_ANY;
  dump_tree (stderr, NULL, node, 0);
}

/* Same as dmp_tree() but limit the nesting to specified depth.  */
void 
dmp_tree1 (node, max_depth)
     tree node;
     int max_depth;
{
  if (max_depth <= 0)
    max_depth = 1;
  dump_tree_state.max_depth = max_depth;
  dump_tree_state.visit_only_once = DMP_TREE_VISIT_ANY;
  dump_tree (stderr, NULL, node, 0);
}

/* Same as dmp_tree() but displays never show a referenced node
   more than once.  */
void 
dmp_tree2 (node)
     tree node;
{
  dump_tree_state.max_depth = INT_MAX;
  dump_tree_state.visit_only_once = DMP_TREE_VISIT_ONCE;
  dump_tree (stderr, NULL, node, 0);
}

/* Called only from tree-dump.c to handle our dmp_tree() types of
   displays when dumping an entire program to a file by specifying
   -fdmp-translation-unit.  */
void 
dmp_tree3 (file, node, flags)
     FILE *file;
     tree node;
     int flags ATTRIBUTE_UNUSED;
{
  int i;
  
  dump_tree_state.max_depth = INT_MAX;
  dump_tree_state.visit_only_once = DMP_TREE_VISIT_ONCE1;
  
  while (node)
    {
      dump_tree (file, NULL, node, 0);
      node = TREE_CHAIN (node);
    }
    
  newline_and_indent (file, 0);
  
  if (type_array_next > 0)
    {
      for (i = 0; i < type_array_next;  ++i)
	dump_tree (file, NULL, type_array[i], 0);
	
      free (type_array);
    }
    
  free_hash_table ();
}

/*-------------------------------------------------------------------*/

#if DMP_TREE_WRAPPED_OUTPUT

/* The three routines below here are what's actually called when fprintf,
   fputc, or fputs are used in the tree dumper.  These are used to
   intercept the output to impose an appropriate line wrapping convention
   on nodes that get too long for the display (lines > wrap_column).  The
   stdio.h names are redefined by macros to call these routines when 
   DMP_TREE_WRAPPED_OUTPUT is set.
   
   The line wrap convention is to wrap only on blanks between the node's
   info.  Blanks within bracketed or quoted info does not count.  The
   wrapped portion is indented to start wherever the node's indented
   kind:address portion of the display ends.  */
   
#undef fprintf
#undef fputc
#undef fputs

int 
dmp_tree_fprintf VPARAMS ((FILE *file, const char *fmt, ...))
{
  int len;
  va_list ap;
  
#ifndef ANSI_PROTOTYPES
  FILE *file;
  char *fmt;
#endif
  
  VA_START (ap, fmt);
#ifndef ANSI_PROTOTYPES
  file = va_arg (ap, FILE *);
  fmt  = va_arg (ap, char *);
#endif
  
  len = vsprintf (&curr_line[line_index], fmt, ap);
  line_index += len;
  
  va_end (ap);
  
  if (curr_line[line_index-1] == '\n')
    {
      if (line_index != 1 || !(prev_line_was_wrapped || prev_line_was_null))
        {
      	  curr_line[line_index] = '\0';
      	  fputs (curr_line, file);
      	  fflush (file);
        }
      prev_line_was_null = (line_index == 1);
      line_index = 0;
    }
  else if (line_index >= wrap_column)
    {
      char c, unwritten_part[MAX_LINE_WRAP+2];
      int  i, end, delimiter, nesting;
      
      prev_line_was_wrapped = 0;
      
      /* Limit how far to the left we'll search to about wrap_column/2 */
      end = wrap_column/2;
      if (end < prefix_len)
        end = prefix_len;
      
      /* Search left the the first blank to the left of the wrap point.
         We assume that bracketed entities (e.g., quoted strings,
         parenthetical entities, etc.) are written with a single
         fprintf() so that we know to ignore blanks embedded within
         pairs of these things.  */
         
      i = line_index - 1;
      delimiter = nesting = 0;
      while (i >= end)
        {
          c = curr_line[i];
	  if (curr_line[i-1] == '\\')
	    --i;
          else if (nesting)
            {
	      if (c == delimiter && --nesting <= 0)
		delimiter = 0;
            }
          else if (c == '"' || c == '\'') {
            delimiter = c; ++nesting;
	  } else if (c == ')') {
	    delimiter = '('; ++nesting;
	  } else if (c == ']') {
	    delimiter = '['; ++nesting;
	  } else if (c == '>') {
	    delimiter = '<'; ++nesting;
	  } else if (c == '}') {
	    delimiter = '{'; ++nesting;
	  } else if (c == ' ' && i < wrap_column)
	    break;
          --i;
        }
        
      if (i < end)
      	return len;
      
      /* The wrapped (unwritten) part is everthing to the right of the
         blank found above.  */
         
      strcpy (unwritten_part, &curr_line[i+1]);
      
      /* Delete trailing blanks on the left part we are going to print
         and print it... */
         
      while (curr_line[i] == ' ' && i >= end)
        --i;
      if (i < end)
      	return len;
      	
      curr_line[i+1] = '\n';
      curr_line[i+2] = '\0';
      prev_line_was_wrapped = 1;
      fputs (curr_line, file);
      fflush (file);
      
      /* Write the wrapped portion, indented by the current prefix_len... */
      
      line_index = prefix_len;
      memset(curr_line, ' ', line_index);
      curr_line[line_index] = '\0';
      
      dmp_tree_fprintf (file, "%s", unwritten_part);
    }
    
  return len;
}

int 
dmp_tree_fputc (c, file)
     int c;
     FILE *file;
{
  dmp_tree_fprintf (file, "%c", c);
  return c;
}

int 
dmp_tree_fputs (s, file)
     const char *s;
     FILE *file;
{
  return dmp_tree_fprintf (file, "%s", s);
}

#endif /* DMP_TREE_WRAPPED_OUTPUT */

/*-------------------------------------------------------------------*/

/* Special routine called for debugging chains only.  This is NOT a
   tree node type.  */

void print_TREE_CHAIN PARAMS ((tree));

void
print_TREE_CHAIN (node)
     tree node;
{
  while (node)
    {
      dump_tree (stderr, NULL, node, 0); /* keep list at same indent */
      node = TREE_CHAIN (node);
    }
}