OSDN Git Service

* builtins.def: Alphabetize.
[pf3gnuchains/gcc-fork.git] / gcc / c-pretty-print.c
index c859cd7..7bb4cb0 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines common to both C and C++ pretty-printers.
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
 
 This file is part of GCC.
@@ -21,43 +21,73 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "real.h"
 #include "c-pretty-print.h"
+#include "c-tree.h"
+
+/* The pretty-printer code is primarily designed to closely follow
+   (GNU) C and C++ grammars.  That is to be contrasted with spaghetti
+   codes we used to have in the past.  Following a structured
+   approach (preferaably the official grammars) is believed to make it
+   much easier o add extensions and nifty pretty-printing effects that
+   takes expresssion or declaration contexts into account.  */
 
 /* literal  */
-static void pp_c_char              PARAMS ((c_pretty_print_info *, int));
-static void pp_c_character_literal PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_bool_literal      PARAMS ((c_pretty_print_info *, tree));
-static bool pp_c_enumerator        PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_integer_literal   PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_real_literal      PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_string_literal    PARAMS ((c_pretty_print_info *, tree));
-
-static void pp_c_primary_expression PARAMS ((c_pretty_print_info *, tree));
-
-static void pp_c_unary_expression PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_multiplicative_expression PARAMS ((c_pretty_print_info *,
-                                                   tree));
-static void pp_c_additive_expression PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_shift_expression PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_relational_expression PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_equality_expression PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_and_expression PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_exclusive_or_expression PARAMS ((c_pretty_print_info *,
-                                                 tree));
-static void pp_c_inclusive_or_expression PARAMS ((c_pretty_print_info *,
-                                                 tree));
-static void pp_c_logical_and_expression PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_conditional_expression PARAMS ((c_pretty_print_info *, tree));
-static void pp_c_assignment_expression PARAMS ((c_pretty_print_info *, tree));
+static void pp_c_char (c_pretty_printer, int);
+static void pp_c_character_literal (c_pretty_printer, tree);
+static void pp_c_bool_literal (c_pretty_printer, tree);
+static bool pp_c_enumerator (c_pretty_printer, tree);
+static void pp_c_integer_literal (c_pretty_printer, tree);
+static void pp_c_real_literal (c_pretty_printer, tree);
+static void pp_c_string_literal (c_pretty_printer, tree);
+
+static void pp_c_primary_expression (c_pretty_printer, tree);
+
+/* postfix-expression  */
+static void pp_c_initializer_list (c_pretty_printer, tree);
+
+static void pp_c_unary_expression (c_pretty_printer, tree);
+static void pp_c_multiplicative_expression (c_pretty_printer, tree);
+static void pp_c_additive_expression (c_pretty_printer, tree);
+static void pp_c_shift_expression (c_pretty_printer, tree);
+static void pp_c_relational_expression (c_pretty_printer, tree);
+static void pp_c_equality_expression (c_pretty_printer, tree);
+static void pp_c_and_expression (c_pretty_printer, tree);
+static void pp_c_exclusive_or_expression (c_pretty_printer, tree);
+static void pp_c_inclusive_or_expression (c_pretty_printer, tree);
+static void pp_c_logical_and_expression (c_pretty_printer, tree);
+static void pp_c_conditional_expression (c_pretty_printer, tree);
+static void pp_c_assignment_expression (c_pretty_printer, tree);
+
+/* declarations.  */
+static void pp_c_declaration_specifiers (c_pretty_printer, tree);
+static void pp_c_init_declarator (c_pretty_printer, tree);
+static void pp_c_declarator (c_pretty_printer, tree);
+static void pp_c_direct_declarator (c_pretty_printer, tree);
+static void pp_c_abstract_declarator (c_pretty_printer, tree);
+static void pp_c_specifier_qualifier_list (c_pretty_printer, tree);
+static void pp_c_simple_type_specifier (c_pretty_printer, tree);
+static void pp_c_parameter_declaration (c_pretty_printer, tree);
+static void pp_c_type_id (c_pretty_printer, tree);
+static void pp_c_storage_class_specifier (c_pretty_printer, tree);
+static void pp_c_function_specifier (c_pretty_printer, tree);
+
+#define pp_buffer(PP) pp_base (PP)->buffer
+#define pp_newline(PP) (pp_newline) (pp_base (PP))
+
 \f
 /* Declarations.  */
 
-/* Print out CV-qualifiers.  Take care of possible extension.  */
+/* Print out CV-qualifiers.  Take care of possible extensions.
+     cv-qualifier:
+        const
+        volatile
+        restrict
+        __restrict__   */
 void
-pp_c_cv_qualifier (ppi, cv)
-     c_pretty_print_info *ppi;
-     int cv;
+pp_c_cv_qualifier (c_pretty_printer ppi, int cv)
 {
   if (cv & TYPE_QUAL_CONST)
     pp_c_identifier (ppi, "const");
@@ -67,17 +97,213 @@ pp_c_cv_qualifier (ppi, cv)
     pp_c_identifier (ppi, flag_isoc99 ? "restrict" : "__restrict__");
 }
 
-\f
-/* Statements.  */
+/*
+  simple-type-specifier:
+     void
+     char
+     short
+     int
+     long
+     float
+     double
+     signed
+     unsigned
+     _Bool                          -- C99
+     _Complex                       -- C99
+     _Imaginary                     -- C99
+     typedef-name.
+
+  GNU extensions.
+  simple-type-specifier:
+      __complex__
+      __vector__   */
+static void
+pp_c_simple_type_specifier (c_pretty_printer ppi, tree t)
+{
+  const enum tree_code code = TREE_CODE (t);
+  switch (code)
+    {
+    case ERROR_MARK:
+      pp_c_identifier (ppi, "<type-error>");
+      break;
+
+#if 0
+    case UNKNOWN_TYPE:
+      pp_c_identifier (ppi, "<unkown-type>");
+      break;
+#endif
+
+    case IDENTIFIER_NODE:
+      pp_c_tree_identifier (ppi, t);
+      break;
+
+    case VOID_TYPE:
+    case BOOLEAN_TYPE:
+    case CHAR_TYPE:
+    case INTEGER_TYPE:
+    case REAL_TYPE:
+      pp_c_tree_identifier (ppi, DECL_NAME (t));
+      break;
+
+    case COMPLEX_TYPE:
+    case VECTOR_TYPE:
+      pp_c_simple_type_specifier (ppi, TYPE_MAIN_VARIANT (TREE_TYPE (t)));
+      if (code == COMPLEX_TYPE)
+       pp_c_identifier (ppi, flag_isoc99 ? "_Complex" : "__complex__");
+      else if (code == VECTOR_TYPE)
+       pp_c_identifier (ppi, "__vector__");
+      break;
+
+    case TYPE_DECL:
+      if (DECL_NAME (t))
+       pp_c_tree_identifier (ppi, DECL_NAME (t));
+      else
+       pp_c_identifier (ppi, "<typedef-error>");
+      break;
+
+    case UNION_TYPE:
+    case RECORD_TYPE:
+    case ENUMERAL_TYPE:
+      if (code == UNION_TYPE)
+       pp_c_identifier (ppi, "union");
+      else if (code == RECORD_TYPE)
+       pp_c_identifier (ppi, "struct");
+      else if (code == ENUMERAL_TYPE)
+       pp_c_identifier (ppi, "enum");
+      else
+       pp_c_identifier (ppi, "<tag-error>");
+
+      if (TYPE_NAME (t))
+       pp_c_tree_identifier (ppi, TYPE_NAME (t));
+      else
+       pp_c_identifier (ppi, "<anonymous>");
+      break;
+
+    default:
+      pp_unsupported_tree (ppi, t);
+    }
+}
+
+/* specifier-qualifier-list:
+      type-specifier specifier-qualifier-list-opt
+      cv-qualifier specifier-qualifier-list-opt  */
+static inline void
+pp_c_specifier_qualifier_list (c_pretty_printer ppi, tree t)
+{
+  pp_c_simple_type_specifier (ppi, TYPE_MAIN_VARIANT (TREE_TYPE (t)));
+  pp_c_cv_qualifier (ppi, TYPE_QUALS (t));
+}
+
+static void
+pp_c_abstract_declarator (c_pretty_printer ppi, tree t)
+{
+  pp_unsupported_tree (ppi, t);
+}
+
+
+static inline void
+pp_c_type_id (c_pretty_printer ppi, tree t)
+{
+  pp_c_specifier_qualifier_list (ppi, t);
+  pp_c_abstract_declarator (ppi, t);
+}
+
+static inline void
+pp_c_storage_class_specifier (c_pretty_printer pp, tree t)
+{
+  if (TREE_CODE (t) == TYPE_DECL)
+    pp_c_identifier (pp, "typedef");
+  else if (DECL_REGISTER (t))
+    pp_c_identifier (pp, "register");
+}
+
+static inline void
+pp_c_function_specifier (c_pretty_printer pp, tree t)
+{
+  if (TREE_CODE (t) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (t))
+    pp_c_identifier (pp, "inline");
+}
+
+static inline void
+pp_c_declaration_specifiers (c_pretty_printer pp, tree t)
+{
+  pp_c_storage_class_specifier (pp, t);
+  pp_c_function_specifier (pp, t);
+  pp_type_specifier (pp, TYPE_MAIN_VARIANT (TREE_TYPE (t)));
+  pp_c_cv_qualifier (pp, TYPE_QUALS (TREE_TYPE (t)));
+}
+
+static inline void
+pp_c_direct_declarator (c_pretty_printer pp, tree t)
+{
+  pp_unsupported_tree (pp, t);
+}
+
+static inline void
+pp_c_declarator (c_pretty_printer pp, tree t)
+{
+  pp_unsupported_tree (pp, t);
+}
+
+static inline void
+pp_c_init_declarator (c_pretty_printer pp, tree t)
+{
+  pp_declarator (pp, t);
+  if (DECL_INITIAL (t))
+    {
+      pp_space (pp);
+      pp_equal (pp);
+      pp_space (pp);
+      pp_c_initializer (pp, DECL_INITIAL (t));
+    }
+}
+
+void
+pp_c_declaration (c_pretty_printer pp, tree t)
+{
+  pp_declaration_specifiers (pp, t);
+  pp_c_init_declarator (pp, t);
+}
+
+static void
+pp_c_parameter_declaration (c_pretty_printer pp, tree t)
+{
+  pp_unsupported_tree (pp, t);
+}
+
+/* Pretty-print ATTRIBUTES using GNU C extension syntax.  */
+void
+pp_c_attributes (c_pretty_printer pp, tree attributes)
+{
+  if (attributes == NULL_TREE)
+    return;
+
+  pp_c_identifier (pp, "__attribute__");
+  pp_c_left_paren (pp);
+  pp_c_left_paren (pp);
+  for (; attributes != NULL_TREE; attributes = TREE_CHAIN (attributes))
+    {
+      pp_tree_identifier (pp, TREE_PURPOSE (attributes));
+      if (TREE_VALUE (attributes))
+       {
+         pp_c_left_paren (pp);
+         pp_c_expression_list (pp, TREE_VALUE (attributes));
+         pp_c_right_paren (pp);
+       }
+
+      if (TREE_CHAIN (attributes))
+       pp_separate_with (pp, ',');
+    }
+  pp_c_right_paren (pp);
+  pp_c_right_paren (pp);
+}
 
 \f
 /* Expressions.  */
 
 /* Print out a c-char.  */
 static void
-pp_c_char (ppi, c)
-     c_pretty_print_info *ppi;
-     int c;
+pp_c_char (c_pretty_printer ppi, int c)
 {
   switch (c)
     {
@@ -113,18 +339,16 @@ pp_c_char (ppi, c)
       break;
     default:
       if (ISPRINT (c))
-       pp_character (ppi, c);
+       pp_character (&ppi->base, c);
       else
-       pp_format_integer (ppi, "\\%03o", (unsigned) c);
+       pp_scalar (ppi, "\\%03o", (unsigned) c);
       break;
     }
 }
 
 /* Print out a STRING literal.  */
 static inline void
-pp_c_string_literal (ppi, s)
-     c_pretty_print_info *ppi;
-     tree s;
+pp_c_string_literal (c_pretty_printer ppi, tree s)
 {
   const char *p = TREE_STRING_POINTER (s);
   int n = TREE_STRING_LENGTH (s) - 1;
@@ -137,9 +361,7 @@ pp_c_string_literal (ppi, s)
 
 /* Print out a CHARACTER literal.  */
 static inline void
-pp_c_character_literal (ppi, c)
-     c_pretty_print_info *ppi;
-     tree c;
+pp_c_character_literal (c_pretty_printer ppi, tree c)
 {
   pp_quote (ppi);
   pp_c_char (ppi, tree_low_cst (c, 0));
@@ -148,24 +370,22 @@ pp_c_character_literal (ppi, c)
 
 /* Print out a BOOLEAN literal.  */
 static inline void
-pp_c_bool_literal (ppi, b)
-     c_pretty_print_info *ppi;
-     tree b;
+pp_c_bool_literal (c_pretty_printer ppi, tree b)
 {
   if (b == boolean_false_node || integer_zerop (b))
     {
-      if (c_language == clk_cplusplus)
+      if (c_dialect_cxx ())
        pp_c_identifier (ppi, "false");
-      else if (c_language == clk_c && flag_isoc99)
+      else if (flag_isoc99)
        pp_c_identifier (ppi, "_False");
       else
        pp_unsupported_tree (ppi, b);
     }
   else if (b == boolean_true_node)
     {
-      if (c_language == clk_cplusplus)
+      if (c_dialect_cxx ())
        pp_c_identifier (ppi, "true");
-      else if (c_language == clk_c && flag_isoc99)
+      else if (flag_isoc99)
        pp_c_identifier (ppi, "_True");
       else
        pp_unsupported_tree (ppi, b);
@@ -174,24 +394,22 @@ pp_c_bool_literal (ppi, b)
     pp_unsupported_tree (ppi, b);
 }
 
-/* Attempt to print out an ENUMERATOR.  Return true on success.  Else return 
+/* Attempt to print out an ENUMERATOR.  Return true on success.  Else return
    false; that means the value was obtained by a cast, in which case
    print out the type-id part of the cast-expression -- the casted value
    is then printed by pp_c_integer_literal.  */
 static bool
-pp_c_enumerator (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_enumerator (c_pretty_printer ppi, tree e)
 {
   tree type = TREE_TYPE (e);
   tree value;
 
   /* Find the name of this constant.  */
-  for (value = TYPE_VALUES (type); 
+  for (value = TYPE_VALUES (type);
        value != NULL_TREE && !tree_int_cst_equal (TREE_VALUE (value), e);
        value = TREE_CHAIN (value))
     ;
-  
+
   if (value != NULL_TREE)
     pp_c_tree_identifier (ppi, TREE_PURPOSE (value));
   else
@@ -202,18 +420,16 @@ pp_c_enumerator (ppi, e)
       pp_c_right_paren (ppi);
       return false;
     }
-  
+
   return true;
 }
 
 /* Print out an INTEGER constant value.  */
 static void
-pp_c_integer_literal (ppi, i)
-     c_pretty_print_info *ppi;
-     tree i;
+pp_c_integer_literal (c_pretty_printer ppi, tree i)
 {
   tree type = TREE_TYPE (i);
-  
+
   if (type == boolean_type_node)
     pp_c_bool_literal (ppi, i);
   else if (type == char_type_node)
@@ -229,14 +445,11 @@ pp_c_integer_literal (ppi, i)
        {
          if (tree_int_cst_sgn (i) < 0)
            {
-             static char format[10]; /* "%x%09999x\0" */
-             if (!format[0])
-               sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4);
-
              pp_c_char (ppi, '-');
              i = build_int_2 (-TREE_INT_CST_LOW (i),
                               ~TREE_INT_CST_HIGH (i) + !TREE_INT_CST_LOW (i));
-             sprintf (pp_buffer (ppi)->digit_buffer, format, 
+             sprintf (pp_buffer (ppi)->digit_buffer,
+                      HOST_WIDE_INT_PRINT_DOUBLE_HEX,
                       TREE_INT_CST_HIGH (i), TREE_INT_CST_LOW (i));
              pp_identifier (ppi, pp_buffer (ppi)->digit_buffer);
 
@@ -245,36 +458,32 @@ pp_c_integer_literal (ppi, i)
     }
 }
 
-/* Print out a REAL value. */
+/* Print out a REAL value.  */
 static inline void
-pp_c_real_literal (ppi, r)
-     c_pretty_print_info *ppi;
-     tree r;
+pp_c_real_literal (c_pretty_printer ppi, tree r)
 {
-  REAL_VALUE_TO_DECIMAL (TREE_REAL_CST (r), "%.16g",
-                        pp_buffer (ppi)->digit_buffer);
+  real_to_decimal (pp_buffer (ppi)->digit_buffer, &TREE_REAL_CST (r),
+                  sizeof (pp_buffer (ppi)->digit_buffer), 0, 1);
   pp_identifier (ppi, pp_buffer(ppi)->digit_buffer);
 }
 
 
 void
-pp_c_literal (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_literal (c_pretty_printer ppi, tree e)
 {
   switch (TREE_CODE (e))
     {
     case INTEGER_CST:
       pp_c_integer_literal (ppi, e);
       break;
-      
+
     case REAL_CST:
       pp_c_real_literal (ppi, e);
       break;
-      
+
     case STRING_CST:
       pp_c_string_literal (ppi, e);
-      break;      
+      break;
 
     default:
       pp_unsupported_tree (ppi, e);
@@ -284,9 +493,7 @@ pp_c_literal (ppi, e)
 
 /* Pretty-print a C primary-expression.  */
 static void
-pp_c_primary_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_primary_expression (c_pretty_printer ppi, tree e)
 {
   switch (TREE_CODE (e))
     {
@@ -305,7 +512,7 @@ pp_c_primary_expression (ppi, e)
     case ERROR_MARK:
       pp_c_identifier (ppi, "<erroneous-expression>");
       break;
-                      
+
     case RESULT_DECL:
       pp_c_identifier (ppi, "<return-value>");
       break;
@@ -316,8 +523,30 @@ pp_c_primary_expression (ppi, e)
       pp_c_literal (ppi, e);
       break;
 
+    case TARGET_EXPR:
+      pp_c_left_paren (ppi);
+      pp_c_identifier (ppi, "__builtin_memcpy");
+      pp_c_left_paren (ppi);
+      pp_ampersand (ppi);
+      pp_c_primary_expression (ppi, TREE_OPERAND (e, 0));
+      pp_separate_with (ppi, ',');
+      pp_ampersand (ppi);
+      pp_initializer (ppi, TREE_OPERAND (e, 1));
+      if (TREE_OPERAND (e, 2))
+       {
+         pp_separate_with (ppi, ',');
+         pp_c_expression (ppi, TREE_OPERAND (e, 2));
+       }
+      pp_c_right_paren (ppi);
+
+    case STMT_EXPR:
+      pp_c_left_paren (ppi);
+      pp_statement (ppi, STMT_EXPR_STMT (e));
+      pp_c_right_paren (ppi);
+      break;
+
     default:
-      /*  Make sure this call won't cause any infinite loop. */
+      /*  Make sure this call won't cause any infinite loop.  */
       pp_c_left_paren (ppi);
       pp_c_expression (ppi, e);
       pp_c_right_paren (ppi);
@@ -325,10 +554,63 @@ pp_c_primary_expression (ppi, e)
     }
 }
 
+/* Print out a C initializer -- also support C compound-literals.  */
+void
+pp_c_initializer (c_pretty_printer ppi, tree e)
+{
+  if (TREE_CODE (e) == CONSTRUCTOR)
+    {
+      enum tree_code code = TREE_CODE (TREE_TYPE (e));
+      if (code == RECORD_TYPE || code == UNION_TYPE || code == ARRAY_TYPE)
+       {
+         pp_left_brace (ppi);
+         pp_c_initializer_list (ppi, e);
+         pp_right_brace (ppi);
+       }
+      else
+       pp_unsupported_tree (ppi, TREE_OPERAND (e, 1));
+    }
+  else
+    pp_assignment_expression (ppi, e);
+}
+
+static void
+pp_c_initializer_list (c_pretty_printer ppi, tree e)
+{
+  tree type = TREE_TYPE (e);
+  const enum tree_code code = TREE_CODE (type);
+
+  if (code == RECORD_TYPE || code == UNION_TYPE || code == ARRAY_TYPE)
+    {
+      tree init = TREE_OPERAND (e, 1);
+      for (; init != NULL_TREE; init = TREE_CHAIN (init))
+       {
+         if (code == RECORD_TYPE || code == UNION_TYPE)
+           {
+             pp_dot (ppi);
+             pp_c_primary_expression (ppi, TREE_PURPOSE (init));
+           }
+         else
+           {
+             pp_c_left_bracket (ppi);
+             if (TREE_PURPOSE (init))
+               pp_c_literal (ppi, TREE_PURPOSE (init));
+             pp_c_right_bracket (ppi);
+           }
+         pp_c_whitespace (ppi);
+         pp_equal (ppi);
+         pp_c_whitespace (ppi);
+         pp_initializer (ppi, TREE_VALUE (init));
+         if (TREE_CHAIN (init))
+           pp_separate_with (ppi, ',');
+       }
+    }
+  else
+    pp_unsupported_tree (ppi, type);
+}
+
 void
-pp_c_postfix_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_postfix_expression (c_pretty_printer ppi, tree e)
 {
   enum tree_code code = TREE_CODE (e);
   switch (code)
@@ -339,6 +621,11 @@ pp_c_postfix_expression (ppi, e)
       pp_identifier (ppi, code == POSTINCREMENT_EXPR ? "++" : "--");
       break;
 
+    case ARROW_EXPR:
+      pp_postfix_expression (ppi, TREE_OPERAND (e, 0));
+      pp_arrow (ppi);
+      break;
+
     case ARRAY_REF:
       pp_postfix_expression (ppi, TREE_OPERAND (e, 0));
       pp_c_left_bracket (ppi);
@@ -353,6 +640,15 @@ pp_c_postfix_expression (ppi, e)
       pp_c_right_paren (ppi);
       break;
 
+    case ABS_EXPR:
+    case FFS_EXPR:
+      pp_c_identifier (ppi,
+                      code == ABS_EXPR ? "__builtin_abs" : "__builtin_ffs");
+      pp_c_left_paren (ppi);
+      pp_c_expression (ppi, TREE_OPERAND (e, 0));
+      pp_c_right_paren (ppi);
+      break;
+
     case COMPONENT_REF:
       {
        tree object = TREE_OPERAND (e, 0);
@@ -370,10 +666,46 @@ pp_c_postfix_expression (ppi, e)
       }
       break;
 
-    case CONSTRUCTOR:
     case COMPLEX_CST:
     case VECTOR_CST:
-      pp_unsupported_tree (ppi, e);
+    case COMPLEX_EXPR:
+      pp_c_left_paren (ppi);
+      pp_type_id (ppi, TREE_TYPE (e));
+      pp_c_right_paren (ppi);
+      pp_left_brace (ppi);
+
+      if (code == COMPLEX_CST)
+       {
+         pp_c_expression (ppi, TREE_REALPART (e));
+         pp_separate_with (ppi, ',');
+         pp_c_expression (ppi, TREE_IMAGPART (e));
+       }
+      else if (code == VECTOR_CST)
+       pp_c_expression_list (ppi, TREE_VECTOR_CST_ELTS (e));
+      else if (code == COMPLEX_EXPR)
+       {
+         pp_c_expression (ppi, TREE_OPERAND (e, 0));
+         pp_separate_with (ppi, ',');
+         pp_c_expression (ppi, TREE_OPERAND (e, 1));
+       }
+
+      pp_right_brace (ppi);
+      break;
+
+    case COMPOUND_LITERAL_EXPR:
+      e = DECL_INITIAL (e);
+      /* Fall through.  */
+    case CONSTRUCTOR:
+      pp_initializer (ppi, e);
+      break;
+
+    case VA_ARG_EXPR:
+      pp_c_identifier (ppi, "__builtin_va_arg");
+      pp_c_left_paren (ppi);
+      pp_assignment_expression (ppi, TREE_OPERAND (e, 0));
+      pp_separate_with (ppi, ',');
+      pp_type_id (ppi, TREE_TYPE (e));
+      pp_c_right_paren (ppi);
       break;
 
     default:
@@ -382,11 +714,9 @@ pp_c_postfix_expression (ppi, e)
     }
 }
 
-/* Print out an expession-list; E is expected to be a TREE_LIST  */
+/* Print out an expression-list; E is expected to be a TREE_LIST  */
 void
-pp_c_expression_list (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_expression_list (c_pretty_printer ppi, tree e)
 {
   for (; e != NULL_TREE; e = TREE_CHAIN (e))
     {
@@ -396,10 +726,25 @@ pp_c_expression_list (ppi, e)
     }
 }
 
+/* unary-expression:
+      postfix-expression
+      ++ cast-expression
+      -- cast-expression
+      unary-operator cast-expression
+      sizeof unary-expression
+      sizeof ( type-id )
+
+  unary-operator: one of
+      * &  + - ! ~
+      
+   GNU extensions.
+   unary-expression:
+      __alignof__ unary-expression
+      __alignof__ ( type-id )
+      __real__ unary-expression
+      __imag__ unary-expression  */
 static void
-pp_c_unary_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_unary_expression (c_pretty_printer ppi, tree e)
 {
   enum tree_code code = TREE_CODE (e);
   switch (code)
@@ -409,20 +754,20 @@ pp_c_unary_expression (ppi, e)
       pp_identifier (ppi, code == PREINCREMENT_EXPR ? "++" : "--");
       pp_c_unary_expression (ppi, TREE_OPERAND (e, 0));
       break;
-      
+
     case ADDR_EXPR:
     case INDIRECT_REF:
-    case CONVERT_EXPR:
     case NEGATE_EXPR:
     case BIT_NOT_EXPR:
     case TRUTH_NOT_EXPR:
+    case CONJ_EXPR:
       if (code == ADDR_EXPR)
        pp_ampersand (ppi);
       else if (code == INDIRECT_REF)
        pp_star (ppi);
       else if (code == NEGATE_EXPR)
        pp_minus (ppi);
-      else if (code == BIT_NOT_EXPR)
+      else if (code == BIT_NOT_EXPR || code == CONJ_EXPR)
        pp_complement (ppi);
       else if (code == TRUTH_NOT_EXPR)
        pp_exclamation (ppi);
@@ -443,6 +788,13 @@ pp_c_unary_expression (ppi, e)
        pp_c_unary_expression (ppi, TREE_OPERAND (e, 0));
       break;
 
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      pp_c_identifier (ppi, code == REALPART_EXPR ? "__real__" : "__imag__");
+      pp_c_whitespace (ppi);
+      pp_unary_expression (ppi, TREE_OPERAND (e, 0));
+      break;
+
     default:
       pp_postfix_expression (ppi, e);
       break;
@@ -450,11 +802,9 @@ pp_c_unary_expression (ppi, e)
 }
 
 void
-pp_c_cast_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_cast_expression (c_pretty_printer ppi, tree e)
 {
-  if (TREE_CODE (e) == CONVERT_EXPR)
+  if (TREE_CODE (e) == CONVERT_EXPR || TREE_CODE (e) == FLOAT_EXPR)
     {
       pp_c_left_paren (ppi);
       pp_type_id (ppi, TREE_TYPE (e));
@@ -466,9 +816,7 @@ pp_c_cast_expression (ppi, e)
 }
 
 static void
-pp_c_multiplicative_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_multiplicative_expression (c_pretty_printer ppi, tree e)
 {
   enum tree_code code = TREE_CODE (e);
   switch (code)
@@ -495,9 +843,7 @@ pp_c_multiplicative_expression (ppi, e)
 }
 
 static inline void
-pp_c_additive_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_additive_expression (c_pretty_printer ppi, tree e)
 {
   enum tree_code code = TREE_CODE (e);
   switch (code)
@@ -521,9 +867,7 @@ pp_c_additive_expression (ppi, e)
 }
 
 static inline void
-pp_c_shift_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_shift_expression (c_pretty_printer ppi, tree e)
 {
   enum tree_code code = TREE_CODE (e);
   switch (code)
@@ -543,9 +887,7 @@ pp_c_shift_expression (ppi, e)
 }
 
 static void
-pp_c_relational_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_relational_expression (c_pretty_printer ppi, tree e)
 {
   enum tree_code code = TREE_CODE (e);
   switch (code)
@@ -575,9 +917,7 @@ pp_c_relational_expression (ppi, e)
 }
 
 static inline void
-pp_c_equality_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_equality_expression (c_pretty_printer ppi, tree e)
 {
   enum tree_code code = TREE_CODE (e);
   switch (code)
@@ -589,8 +929,8 @@ pp_c_equality_expression (ppi, e)
       pp_identifier (ppi, code == EQ_EXPR ? "==" : "!=");
       pp_c_whitespace (ppi);
       pp_c_relational_expression (ppi, TREE_OPERAND (e, 1));
-      break;   
-      
+      break;
+
     default:
       pp_c_relational_expression (ppi, e);
       break;
@@ -598,9 +938,7 @@ pp_c_equality_expression (ppi, e)
 }
 
 static inline void
-pp_c_and_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_and_expression (c_pretty_printer ppi, tree e)
 {
   if (TREE_CODE (e) == BIT_AND_EXPR)
     {
@@ -615,9 +953,7 @@ pp_c_and_expression (ppi, e)
 }
 
 static inline void
-pp_c_exclusive_or_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_exclusive_or_expression (c_pretty_printer ppi, tree e)
 {
   if (TREE_CODE (e) == BIT_XOR_EXPR)
     {
@@ -632,9 +968,7 @@ pp_c_exclusive_or_expression (ppi, e)
 }
 
 static inline void
-pp_c_inclusive_or_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_inclusive_or_expression (c_pretty_printer ppi, tree e)
 {
   if (TREE_CODE (e) == BIT_IOR_EXPR)
     {
@@ -649,9 +983,7 @@ pp_c_inclusive_or_expression (ppi, e)
 }
 
 static inline void
-pp_c_logical_and_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_logical_and_expression (c_pretty_printer ppi, tree e)
 {
   if (TREE_CODE (e) == TRUTH_ANDIF_EXPR)
     {
@@ -666,9 +998,7 @@ pp_c_logical_and_expression (ppi, e)
 }
 
 void
-pp_c_logical_or_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_logical_or_expression (c_pretty_printer ppi, tree e)
 {
   if (TREE_CODE (e) == TRUTH_ORIF_EXPR)
     {
@@ -683,9 +1013,7 @@ pp_c_logical_or_expression (ppi, e)
 }
 
 static void
-pp_c_conditional_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_conditional_expression (c_pretty_printer ppi, tree e)
 {
   if (TREE_CODE (e) == COND_EXPR)
     {
@@ -706,16 +1034,14 @@ pp_c_conditional_expression (ppi, e)
 
 /* Pretty-print a C assignment-expression.  */
 static void
-pp_c_assignment_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_assignment_expression (c_pretty_printer ppi, tree e)
 {
-  if (TREE_CODE (e) == MODIFY_EXPR)
+  if (TREE_CODE (e) == MODIFY_EXPR || TREE_CODE (e) == INIT_EXPR)
     {
       pp_c_unary_expression (ppi, TREE_OPERAND (e, 0));
       pp_c_maybe_whitespace (ppi);
       pp_equal (ppi);
-      pp_whitespace (ppi);
+      pp_space (ppi);
       pp_c_assignment_expression (ppi, TREE_OPERAND (e, 1));
     }
   else
@@ -724,16 +1050,14 @@ pp_c_assignment_expression (ppi, e)
 
 /* Pretty-print an expression.  */
 void
-pp_c_expression (ppi, e)
-     c_pretty_print_info *ppi;
-     tree e;
+pp_c_expression (c_pretty_printer ppi, tree e)
 {
   switch (TREE_CODE (e))
     {
     case INTEGER_CST:
       pp_c_integer_literal (ppi, e);
       break;
-      
+
     case REAL_CST:
       pp_c_real_literal (ppi, e);
       break;
@@ -741,7 +1065,7 @@ pp_c_expression (ppi, e)
     case STRING_CST:
       pp_c_string_literal (ppi, e);
       break;
-      
+
     case FUNCTION_DECL:
     case VAR_DECL:
     case CONST_DECL:
@@ -750,21 +1074,45 @@ pp_c_expression (ppi, e)
     case FIELD_DECL:
     case LABEL_DECL:
     case ERROR_MARK:
+    case TARGET_EXPR:
+    case STMT_EXPR:
       pp_c_primary_expression (ppi, e);
       break;
 
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
+    case ARROW_EXPR:
     case ARRAY_REF:
     case CALL_EXPR:
     case COMPONENT_REF:
-    case CONSTRUCTOR:
     case COMPLEX_CST:
     case VECTOR_CST:
+    case ABS_EXPR:
+    case FFS_EXPR:
+    case CONSTRUCTOR:
+    case COMPOUND_LITERAL_EXPR:
+    case COMPLEX_EXPR:
+    case VA_ARG_EXPR:
       pp_c_postfix_expression (ppi, e);
       break;
 
+    case CONJ_EXPR:
+    case ADDR_EXPR:
+    case INDIRECT_REF:
+    case NEGATE_EXPR:
+    case BIT_NOT_EXPR:
+    case TRUTH_NOT_EXPR:
+    case PREINCREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+    case SIZEOF_EXPR:
+    case ALIGNOF_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      pp_c_unary_expression (ppi, e);
+      break;
+
     case CONVERT_EXPR:
+    case FLOAT_EXPR:
       pp_c_cast_expression (ppi, e);
       break;
 
@@ -811,6 +1159,7 @@ pp_c_expression (ppi, e)
       break;
 
     case MODIFY_EXPR:
+    case INIT_EXPR:
       pp_c_assignment_expression (ppi, e);
       break;
 
@@ -825,7 +1174,7 @@ pp_c_expression (ppi, e)
       pp_assignment_expression (ppi, TREE_OPERAND (e, 1));
       pp_c_right_paren (ppi);
       break;
-                    
+
 
     default:
       pp_unsupported_tree (ppi, e);
@@ -833,3 +1182,252 @@ pp_c_expression (ppi, e)
     }
 }
 
+\f
+/* Statements.  */
+void
+pp_c_statement (c_pretty_printer ppi, tree stmt)
+{
+  const enum tree_code code = TREE_CODE (stmt);
+  switch (code)
+    {
+    case LABEL_STMT:
+    case CASE_LABEL:
+      pp_newline (ppi);
+      if (code == LABEL_STMT)
+       pp_tree_identifier (ppi, DECL_NAME (LABEL_STMT_LABEL (stmt)));
+      else if (code == LABEL_STMT)
+       {
+         if (CASE_LOW (stmt) == NULL_TREE)
+           pp_identifier (ppi, "default");
+         else
+           {
+             pp_c_identifier (ppi, "case");
+             pp_c_whitespace (ppi);
+             pp_conditional_expression (ppi, CASE_LOW (stmt));
+             if (CASE_HIGH (stmt))
+               {
+                 pp_identifier (ppi, "...");
+                 pp_conditional_expression (ppi, CASE_HIGH (stmt));
+               }
+           }
+       }
+      pp_colon (ppi);
+      pp_newline_and_indent (ppi, 3);
+      break;
+
+    case COMPOUND_STMT:
+      pp_left_brace (ppi);
+      pp_newline_and_indent (ppi, 3);
+      for (stmt = COMPOUND_BODY (stmt); stmt; stmt = TREE_CHAIN (stmt))
+       pp_c_statement (ppi, stmt);
+      pp_newline_and_indent (ppi, -3);
+      pp_right_brace (ppi);
+      pp_newline (ppi);
+      break;
+
+    case EXPR_STMT:
+    case CLEANUP_STMT:
+      pp_newline (ppi);
+      pp_c_expression (ppi, code == EXPR_STMT
+                      ? EXPR_STMT_EXPR (stmt)
+                      : CLEANUP_EXPR (stmt));
+      pp_semicolon (ppi);
+      pp_newline (ppi);
+      break;
+
+    case IF_STMT:
+      pp_c_identifier (ppi, "if");
+      pp_space (ppi);
+      pp_c_left_paren (ppi);
+      pp_c_expression (ppi, IF_COND (stmt));
+      pp_right_paren (ppi);
+      pp_newline_and_indent (ppi, 3);
+      pp_statement (ppi, THEN_CLAUSE (stmt));
+      pp_newline_and_indent (ppi, -3);
+      if (ELSE_CLAUSE (stmt))
+       {
+         tree else_clause = ELSE_CLAUSE (stmt);
+         pp_c_identifier (ppi, "else");
+         if (TREE_CODE (else_clause) == IF_STMT)
+           pp_c_whitespace (ppi);
+         else
+           pp_newline_and_indent (ppi, 3);
+         pp_statement (ppi, else_clause);
+         if (TREE_CODE (else_clause) != IF_STMT)
+           pp_newline_and_indent (ppi, -3);
+       }
+      break;
+
+    case SWITCH_STMT:
+      pp_newline (ppi);
+      pp_c_identifier (ppi, "switch");
+      pp_space (ppi);
+      pp_c_left_paren (ppi);
+      pp_c_expression (ppi, SWITCH_COND (stmt));
+      pp_right_paren (ppi);
+      pp_newline_and_indent (ppi, 3);
+      pp_statement (ppi, SWITCH_BODY (stmt));
+      pp_newline_and_indent (ppi, -3);
+      break;
+
+    case WHILE_STMT:
+      pp_c_identifier (ppi, "while");
+      pp_space (ppi);
+      pp_c_left_paren (ppi);
+      pp_c_expression (ppi, WHILE_COND (stmt));
+      pp_right_paren (ppi);
+      pp_newline_and_indent (ppi, 3);
+      pp_statement (ppi, WHILE_BODY (stmt));
+      pp_newline_and_indent (ppi, -3);
+      break;
+
+    case DO_STMT:
+      pp_c_identifier (ppi, "do");
+      pp_newline_and_indent (ppi, 3);
+      pp_statement (ppi, DO_BODY (stmt));
+      pp_newline_and_indent (ppi, -3);
+      pp_c_identifier (ppi, "while");
+      pp_space (ppi);
+      pp_c_left_paren (ppi);
+      pp_c_expression (ppi, DO_COND (stmt));
+      pp_c_right_paren (ppi);
+      pp_semicolon (ppi);
+      pp_newline (ppi);
+      break;
+
+    case FOR_STMT:
+      pp_c_identifier (ppi, "for");
+      pp_space (ppi);
+      pp_c_left_paren (ppi);
+      pp_statement (ppi, FOR_INIT_STMT (stmt));
+      pp_c_whitespace (ppi);
+      if (FOR_COND (stmt))
+       pp_c_expression (ppi, FOR_COND (stmt));
+      pp_semicolon (ppi);
+      pp_c_whitespace (ppi);
+      if (FOR_EXPR (stmt))
+       pp_c_expression (ppi, FOR_EXPR (stmt));
+      pp_right_paren (ppi);
+      pp_newline_and_indent (ppi, 3);
+      pp_statement (ppi, FOR_BODY (stmt));
+      pp_newline_and_indent (ppi, -3);
+      break;
+
+    case BREAK_STMT:
+    case CONTINUE_STMT:
+      pp_newline (ppi);
+      pp_identifier (ppi, code == BREAK_STMT ? "break" : "continue");
+      pp_semicolon (ppi);
+      pp_newline (ppi);
+      break;
+
+    case RETURN_STMT:
+    case GOTO_STMT:
+      {
+       tree e = code == RETURN_STMT
+         ? RETURN_STMT_EXPR (stmt)
+         : GOTO_DESTINATION (stmt);
+
+       pp_newline (ppi);
+       pp_c_identifier (ppi, code == RETURN_STMT ? "return" : "goto");
+       if (e)
+         pp_c_expression (ppi, e);
+       pp_semicolon (ppi);
+       pp_newline (ppi);
+      }
+      break;
+
+    case SCOPE_STMT:
+      if (!SCOPE_NULLIFIED_P (stmt) && SCOPE_NO_CLEANUPS_P (stmt))
+       {
+         if (SCOPE_BEGIN_P (stmt))
+           {
+             pp_left_brace (ppi);
+             pp_newline_and_indent (ppi, 3);
+           }
+         else if (SCOPE_END_P (stmt))
+           {
+             pp_right_brace (ppi);
+             pp_newline_and_indent (ppi, -3);
+           }
+       }
+      break;
+
+    case DECL_STMT:
+      pp_declaration (ppi, DECL_STMT_DECL (stmt));
+      pp_semicolon (ppi);
+      pp_newline (ppi);
+      break;
+
+    case ASM_STMT:
+      {
+       bool has_volatile_p = ASM_VOLATILE_P (stmt);
+       bool is_extended = has_volatile_p || ASM_INPUTS (stmt)
+         || ASM_OUTPUTS (stmt) || ASM_CLOBBERS (stmt);
+       pp_c_identifier (ppi, is_extended ? "__asm__" : "asm");
+       if (has_volatile_p)
+         pp_c_identifier (ppi, "__volatile__");
+       pp_space (ppi);
+       pp_c_left_paren (ppi);
+       pp_c_string_literal (ppi, ASM_STRING (stmt));
+       if (is_extended)
+         {
+           pp_space (ppi);
+           pp_separate_with (ppi, ':');
+           if (ASM_OUTPUTS (stmt))
+             pp_c_expression (ppi, ASM_OUTPUTS (stmt));
+           pp_space (ppi);
+           pp_separate_with (ppi, ':');
+           if (ASM_INPUTS (stmt))
+             pp_c_expression (ppi, ASM_INPUTS (stmt));
+           pp_space (ppi);
+           pp_separate_with (ppi, ':');
+           if (ASM_CLOBBERS (stmt))
+             pp_c_expression (ppi, ASM_CLOBBERS (stmt));
+         }
+       pp_right_paren (ppi);
+       pp_newline (ppi);
+      }
+      break;
+
+    case FILE_STMT:
+      pp_c_identifier (ppi, "__FILE__");
+      pp_space (ppi);
+      pp_equal (ppi);
+      pp_c_whitespace (ppi);
+      pp_c_identifier (ppi, FILE_STMT_FILENAME (stmt));
+      pp_semicolon (ppi);
+      pp_newline (ppi);
+      break;
+
+    default:
+      pp_unsupported_tree (ppi, stmt);
+    }
+
+}
+
+\f
+/* Initialize the PRETTY-PRINTER for handling C codes.  */
+void
+pp_c_pretty_printer_init (c_pretty_printer pp)
+{
+  pp->offset_list               = 0;
+
+  pp->declaration               = pp_c_declaration;
+  pp->declaration_specifiers    = pp_c_declaration_specifiers;
+  pp->type_specifier            = pp_c_simple_type_specifier;
+  pp->declarator                = pp_c_declarator;
+  pp->direct_declarator         = pp_c_direct_declarator;
+  pp->parameter_declaration     = pp_c_parameter_declaration;
+  pp->type_id                   = pp_c_type_id;
+
+  pp->statement                 = pp_c_statement;
+
+  pp->primary_expression        = pp_c_primary_expression;
+  pp->postfix_expression        = pp_c_postfix_expression;
+  pp->unary_expression          = pp_c_unary_expression;
+  pp->initializer               = pp_c_initializer;
+  pp->multiplicative_expression = pp_c_multiplicative_expression;
+  pp->conditional_expression    = pp_c_conditional_expression;
+  pp->assignment_expression     = pp_c_assignment_expression;
+}