138fd1498Szrj /* Print GENERIC declaration (functions, variables, types) trees coming from
238fd1498Szrj    the C and C++ front-ends as well as macros in Ada syntax.
338fd1498Szrj    Copyright (C) 2010-2018 Free Software Foundation, Inc.
438fd1498Szrj    Adapted from tree-pretty-print.c by Arnaud Charlet  <charlet@adacore.com>
538fd1498Szrj 
638fd1498Szrj This file is part of GCC.
738fd1498Szrj 
838fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
938fd1498Szrj the terms of the GNU General Public License as published by the Free
1038fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1138fd1498Szrj version.
1238fd1498Szrj 
1338fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1438fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1538fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1638fd1498Szrj for more details.
1738fd1498Szrj 
1838fd1498Szrj You should have received a copy of the GNU General Public License
1938fd1498Szrj along with GCC; see the file COPYING3.  If not see
2038fd1498Szrj <http://www.gnu.org/licenses/>.  */
2138fd1498Szrj 
2238fd1498Szrj #include "config.h"
2338fd1498Szrj #include "system.h"
2438fd1498Szrj #include "coretypes.h"
2538fd1498Szrj #include "tm.h"
2638fd1498Szrj #include "tree.h"
2738fd1498Szrj #include "c-ada-spec.h"
2838fd1498Szrj #include "fold-const.h"
2938fd1498Szrj #include "c-pragma.h"
3038fd1498Szrj #include "cpp-id-data.h"
3138fd1498Szrj #include "stringpool.h"
3238fd1498Szrj #include "attribs.h"
3338fd1498Szrj 
3438fd1498Szrj /* Local functions, macros and variables.  */
3538fd1498Szrj static int  dump_ada_node (pretty_printer *, tree, tree, int, bool, bool);
3638fd1498Szrj static int  dump_ada_declaration (pretty_printer *, tree, tree, int);
3738fd1498Szrj static void dump_ada_structure (pretty_printer *, tree, tree, int, bool);
3838fd1498Szrj static char *to_ada_name (const char *, unsigned int, bool *);
3938fd1498Szrj 
4038fd1498Szrj #define INDENT(SPACE) \
4138fd1498Szrj   do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
4238fd1498Szrj 
4338fd1498Szrj #define INDENT_INCR 3
4438fd1498Szrj 
4538fd1498Szrj /* Global hook used to perform C++ queries on nodes.  */
4638fd1498Szrj static int (*cpp_check) (tree, cpp_operation) = NULL;
4738fd1498Szrj 
4838fd1498Szrj /* Global variables used in macro-related callbacks.  */
4938fd1498Szrj static int max_ada_macros;
5038fd1498Szrj static int store_ada_macro_index;
5138fd1498Szrj static const char *macro_source_file;
5238fd1498Szrj 
5338fd1498Szrj /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
5438fd1498Szrj    as max length PARAM_LEN of arguments for fun_like macros, and also set
5538fd1498Szrj    SUPPORTED to 0 if the macro cannot be mapped to an Ada construct.  */
5638fd1498Szrj 
5738fd1498Szrj static void
macro_length(const cpp_macro * macro,int * supported,int * buffer_len,int * param_len)5838fd1498Szrj macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
5938fd1498Szrj 	      int *param_len)
6038fd1498Szrj {
6138fd1498Szrj   int i;
6238fd1498Szrj   unsigned j;
6338fd1498Szrj 
6438fd1498Szrj   *supported = 1;
6538fd1498Szrj   *buffer_len = 0;
6638fd1498Szrj   *param_len = 0;
6738fd1498Szrj 
6838fd1498Szrj   if (macro->fun_like)
6938fd1498Szrj     {
7038fd1498Szrj       (*param_len)++;
7138fd1498Szrj       for (i = 0; i < macro->paramc; i++)
7238fd1498Szrj 	{
7338fd1498Szrj 	  cpp_hashnode *param = macro->params[i];
7438fd1498Szrj 
7538fd1498Szrj 	  *param_len += NODE_LEN (param);
7638fd1498Szrj 
7738fd1498Szrj 	  if (i + 1 < macro->paramc)
7838fd1498Szrj 	    {
7938fd1498Szrj 	      *param_len += 2;  /* ", " */
8038fd1498Szrj 	    }
8138fd1498Szrj 	  else if (macro->variadic)
8238fd1498Szrj 	    {
8338fd1498Szrj 	      *supported = 0;
8438fd1498Szrj 	      return;
8538fd1498Szrj 	    }
8638fd1498Szrj 	}
8738fd1498Szrj       *param_len += 2;  /* ")\0" */
8838fd1498Szrj     }
8938fd1498Szrj 
9038fd1498Szrj   for (j = 0; j < macro->count; j++)
9138fd1498Szrj     {
9238fd1498Szrj       cpp_token *token = &macro->exp.tokens[j];
9338fd1498Szrj 
9438fd1498Szrj       if (token->flags & PREV_WHITE)
9538fd1498Szrj 	(*buffer_len)++;
9638fd1498Szrj 
9738fd1498Szrj       if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
9838fd1498Szrj 	{
9938fd1498Szrj 	  *supported = 0;
10038fd1498Szrj 	  return;
10138fd1498Szrj 	}
10238fd1498Szrj 
10338fd1498Szrj       if (token->type == CPP_MACRO_ARG)
10438fd1498Szrj 	*buffer_len +=
10538fd1498Szrj 	  NODE_LEN (macro->params[token->val.macro_arg.arg_no - 1]);
10638fd1498Szrj       else
10738fd1498Szrj 	/* Include enough extra space to handle e.g. special characters.  */
10838fd1498Szrj 	*buffer_len += (cpp_token_len (token) + 1) * 8;
10938fd1498Szrj     }
11038fd1498Szrj 
11138fd1498Szrj   (*buffer_len)++;
11238fd1498Szrj }
11338fd1498Szrj 
11438fd1498Szrj /* Dump all digits/hex chars from NUMBER to BUFFER and return a pointer
11538fd1498Szrj    to the character after the last character written.  If FLOAT_P is true,
11638fd1498Szrj    this is a floating-point number.  */
11738fd1498Szrj 
11838fd1498Szrj static unsigned char *
dump_number(unsigned char * number,unsigned char * buffer,bool float_p)11938fd1498Szrj dump_number (unsigned char *number, unsigned char *buffer, bool float_p)
12038fd1498Szrj {
12138fd1498Szrj   while (*number != '\0'
12238fd1498Szrj 	 && *number != (float_p ? 'F' : 'U')
12338fd1498Szrj 	 && *number != (float_p ? 'f' : 'u')
12438fd1498Szrj 	 && *number != 'l'
12538fd1498Szrj 	 && *number != 'L')
12638fd1498Szrj     *buffer++ = *number++;
12738fd1498Szrj 
12838fd1498Szrj   return buffer;
12938fd1498Szrj }
13038fd1498Szrj 
13138fd1498Szrj /* Handle escape character C and convert to an Ada character into BUFFER.
13238fd1498Szrj    Return a pointer to the character after the last character written, or
13338fd1498Szrj    NULL if the escape character is not supported.  */
13438fd1498Szrj 
13538fd1498Szrj static unsigned char *
handle_escape_character(unsigned char * buffer,char c)13638fd1498Szrj handle_escape_character (unsigned char *buffer, char c)
13738fd1498Szrj {
13838fd1498Szrj   switch (c)
13938fd1498Szrj     {
14038fd1498Szrj       case '"':
14138fd1498Szrj 	*buffer++ = '"';
14238fd1498Szrj 	*buffer++ = '"';
14338fd1498Szrj 	break;
14438fd1498Szrj 
14538fd1498Szrj       case 'n':
14638fd1498Szrj 	strcpy ((char *) buffer, "\" & ASCII.LF & \"");
14738fd1498Szrj 	buffer += 16;
14838fd1498Szrj 	break;
14938fd1498Szrj 
15038fd1498Szrj       case 'r':
15138fd1498Szrj 	strcpy ((char *) buffer, "\" & ASCII.CR & \"");
15238fd1498Szrj 	buffer += 16;
15338fd1498Szrj 	break;
15438fd1498Szrj 
15538fd1498Szrj       case 't':
15638fd1498Szrj 	strcpy ((char *) buffer, "\" & ASCII.HT & \"");
15738fd1498Szrj 	buffer += 16;
15838fd1498Szrj 	break;
15938fd1498Szrj 
16038fd1498Szrj       default:
16138fd1498Szrj 	return NULL;
16238fd1498Szrj     }
16338fd1498Szrj 
16438fd1498Szrj   return buffer;
16538fd1498Szrj }
16638fd1498Szrj 
16738fd1498Szrj /* Callback used to count the number of macros from cpp_forall_identifiers.
16838fd1498Szrj    PFILE and V are not used.  NODE is the current macro to consider.  */
16938fd1498Szrj 
17038fd1498Szrj static int
count_ada_macro(cpp_reader * pfile ATTRIBUTE_UNUSED,cpp_hashnode * node,void * v ATTRIBUTE_UNUSED)17138fd1498Szrj count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node,
17238fd1498Szrj 		 void *v ATTRIBUTE_UNUSED)
17338fd1498Szrj {
17438fd1498Szrj   const cpp_macro *macro = node->value.macro;
17538fd1498Szrj 
17638fd1498Szrj   if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
17738fd1498Szrj       && macro->count
17838fd1498Szrj       && *NODE_NAME (node) != '_'
17938fd1498Szrj       && LOCATION_FILE (macro->line) == macro_source_file)
18038fd1498Szrj     max_ada_macros++;
18138fd1498Szrj 
18238fd1498Szrj   return 1;
18338fd1498Szrj }
18438fd1498Szrj 
18538fd1498Szrj /* Callback used to store relevant macros from cpp_forall_identifiers.
18638fd1498Szrj    PFILE is not used.  NODE is the current macro to store if relevant.
18738fd1498Szrj    MACROS is an array of cpp_hashnode* used to store NODE.  */
18838fd1498Szrj 
18938fd1498Szrj static int
store_ada_macro(cpp_reader * pfile ATTRIBUTE_UNUSED,cpp_hashnode * node,void * macros)19038fd1498Szrj store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED,
19138fd1498Szrj 		 cpp_hashnode *node, void *macros)
19238fd1498Szrj {
19338fd1498Szrj   const cpp_macro *macro = node->value.macro;
19438fd1498Szrj 
19538fd1498Szrj   if (node->type == NT_MACRO
19638fd1498Szrj       && !(node->flags & NODE_BUILTIN)
19738fd1498Szrj       && macro->count
19838fd1498Szrj       && *NODE_NAME (node) != '_'
19938fd1498Szrj       && LOCATION_FILE (macro->line) == macro_source_file)
20038fd1498Szrj     ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
20138fd1498Szrj 
20238fd1498Szrj   return 1;
20338fd1498Szrj }
20438fd1498Szrj 
20538fd1498Szrj /* Callback used to compare (during qsort) macros.  NODE1 and NODE2 are the
20638fd1498Szrj    two macro nodes to compare.  */
20738fd1498Szrj 
20838fd1498Szrj static int
compare_macro(const void * node1,const void * node2)20938fd1498Szrj compare_macro (const void *node1, const void *node2)
21038fd1498Szrj {
21138fd1498Szrj   typedef const cpp_hashnode *const_hnode;
21238fd1498Szrj 
21338fd1498Szrj   const_hnode n1 = *(const const_hnode *) node1;
21438fd1498Szrj   const_hnode n2 = *(const const_hnode *) node2;
21538fd1498Szrj 
21638fd1498Szrj   return n1->value.macro->line - n2->value.macro->line;
21738fd1498Szrj }
21838fd1498Szrj 
21938fd1498Szrj /* Dump in PP all relevant macros appearing in FILE.  */
22038fd1498Szrj 
22138fd1498Szrj static void
dump_ada_macros(pretty_printer * pp,const char * file)22238fd1498Szrj dump_ada_macros (pretty_printer *pp, const char* file)
22338fd1498Szrj {
22438fd1498Szrj   int num_macros = 0, prev_line = -1;
22538fd1498Szrj   cpp_hashnode **macros;
22638fd1498Szrj 
22738fd1498Szrj   /* Initialize file-scope variables.  */
22838fd1498Szrj   max_ada_macros = 0;
22938fd1498Szrj   store_ada_macro_index = 0;
23038fd1498Szrj   macro_source_file = file;
23138fd1498Szrj 
23238fd1498Szrj   /* Count all potentially relevant macros, and then sort them by sloc.  */
23338fd1498Szrj   cpp_forall_identifiers (parse_in, count_ada_macro, NULL);
23438fd1498Szrj   macros = XALLOCAVEC (cpp_hashnode *, max_ada_macros);
23538fd1498Szrj   cpp_forall_identifiers (parse_in, store_ada_macro, macros);
23638fd1498Szrj   qsort (macros, max_ada_macros, sizeof (cpp_hashnode *), compare_macro);
23738fd1498Szrj 
23838fd1498Szrj   for (int j = 0; j < max_ada_macros; j++)
23938fd1498Szrj     {
24038fd1498Szrj       cpp_hashnode *node = macros[j];
24138fd1498Szrj       const cpp_macro *macro = node->value.macro;
24238fd1498Szrj       unsigned i;
24338fd1498Szrj       int supported = 1, prev_is_one = 0, buffer_len, param_len;
24438fd1498Szrj       int is_string = 0, is_char = 0;
24538fd1498Szrj       char *ada_name;
24638fd1498Szrj       unsigned char *s, *params, *buffer, *buf_param, *char_one = NULL, *tmp;
24738fd1498Szrj 
24838fd1498Szrj       macro_length (macro, &supported, &buffer_len, &param_len);
24938fd1498Szrj       s = buffer = XALLOCAVEC (unsigned char, buffer_len);
25038fd1498Szrj       params = buf_param = XALLOCAVEC (unsigned char, param_len);
25138fd1498Szrj 
25238fd1498Szrj       if (supported)
25338fd1498Szrj 	{
25438fd1498Szrj 	  if (macro->fun_like)
25538fd1498Szrj 	    {
25638fd1498Szrj 	      *buf_param++ = '(';
25738fd1498Szrj 	      for (i = 0; i < macro->paramc; i++)
25838fd1498Szrj 		{
25938fd1498Szrj 		  cpp_hashnode *param = macro->params[i];
26038fd1498Szrj 
26138fd1498Szrj 		  memcpy (buf_param, NODE_NAME (param), NODE_LEN (param));
26238fd1498Szrj 		  buf_param += NODE_LEN (param);
26338fd1498Szrj 
26438fd1498Szrj 		  if (i + 1 < macro->paramc)
26538fd1498Szrj 		    {
26638fd1498Szrj 		      *buf_param++ = ',';
26738fd1498Szrj 		      *buf_param++ = ' ';
26838fd1498Szrj 		    }
26938fd1498Szrj 		  else if (macro->variadic)
27038fd1498Szrj 		    {
27138fd1498Szrj 		      supported = 0;
27238fd1498Szrj 		      break;
27338fd1498Szrj 		    }
27438fd1498Szrj 		}
27538fd1498Szrj 	      *buf_param++ = ')';
27638fd1498Szrj 	      *buf_param = '\0';
27738fd1498Szrj 	    }
27838fd1498Szrj 
27938fd1498Szrj 	  for (i = 0; supported && i < macro->count; i++)
28038fd1498Szrj 	    {
28138fd1498Szrj 	      cpp_token *token = &macro->exp.tokens[i];
28238fd1498Szrj 	      int is_one = 0;
28338fd1498Szrj 
28438fd1498Szrj 	      if (token->flags & PREV_WHITE)
28538fd1498Szrj 		*buffer++ = ' ';
28638fd1498Szrj 
28738fd1498Szrj 	      if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
28838fd1498Szrj 		{
28938fd1498Szrj 		  supported = 0;
29038fd1498Szrj 		  break;
29138fd1498Szrj 		}
29238fd1498Szrj 
29338fd1498Szrj 	      switch (token->type)
29438fd1498Szrj 		{
29538fd1498Szrj 		  case CPP_MACRO_ARG:
29638fd1498Szrj 		    {
29738fd1498Szrj 		      cpp_hashnode *param =
29838fd1498Szrj 			macro->params[token->val.macro_arg.arg_no - 1];
29938fd1498Szrj 		      memcpy (buffer, NODE_NAME (param), NODE_LEN (param));
30038fd1498Szrj 		      buffer += NODE_LEN (param);
30138fd1498Szrj 		    }
30238fd1498Szrj 		    break;
30338fd1498Szrj 
30438fd1498Szrj 		  case CPP_EQ_EQ:       *buffer++ = '='; break;
30538fd1498Szrj 		  case CPP_GREATER:     *buffer++ = '>'; break;
30638fd1498Szrj 		  case CPP_LESS:        *buffer++ = '<'; break;
30738fd1498Szrj 		  case CPP_PLUS:        *buffer++ = '+'; break;
30838fd1498Szrj 		  case CPP_MINUS:       *buffer++ = '-'; break;
30938fd1498Szrj 		  case CPP_MULT:        *buffer++ = '*'; break;
31038fd1498Szrj 		  case CPP_DIV:         *buffer++ = '/'; break;
31138fd1498Szrj 		  case CPP_COMMA:       *buffer++ = ','; break;
31238fd1498Szrj 		  case CPP_OPEN_SQUARE:
31338fd1498Szrj 		  case CPP_OPEN_PAREN:  *buffer++ = '('; break;
31438fd1498Szrj 		  case CPP_CLOSE_SQUARE: /* fallthrough */
31538fd1498Szrj 		  case CPP_CLOSE_PAREN: *buffer++ = ')'; break;
31638fd1498Szrj 		  case CPP_DEREF:       /* fallthrough */
31738fd1498Szrj 		  case CPP_SCOPE:       /* fallthrough */
31838fd1498Szrj 		  case CPP_DOT:         *buffer++ = '.'; break;
31938fd1498Szrj 
32038fd1498Szrj 		  case CPP_EQ:          *buffer++ = ':'; *buffer++ = '='; break;
32138fd1498Szrj 		  case CPP_NOT_EQ:      *buffer++ = '/'; *buffer++ = '='; break;
32238fd1498Szrj 		  case CPP_GREATER_EQ:  *buffer++ = '>'; *buffer++ = '='; break;
32338fd1498Szrj 		  case CPP_LESS_EQ:     *buffer++ = '<'; *buffer++ = '='; break;
32438fd1498Szrj 
32538fd1498Szrj 		  case CPP_NOT:
32638fd1498Szrj 		    *buffer++ = 'n'; *buffer++ = 'o'; *buffer++ = 't'; break;
32738fd1498Szrj 		  case CPP_MOD:
32838fd1498Szrj 		    *buffer++ = 'm'; *buffer++ = 'o'; *buffer++ = 'd'; break;
32938fd1498Szrj 		  case CPP_AND:
33038fd1498Szrj 		    *buffer++ = 'a'; *buffer++ = 'n'; *buffer++ = 'd'; break;
33138fd1498Szrj 		  case CPP_OR:
33238fd1498Szrj 		    *buffer++ = 'o'; *buffer++ = 'r'; break;
33338fd1498Szrj 		  case CPP_XOR:
33438fd1498Szrj 		    *buffer++ = 'x'; *buffer++ = 'o'; *buffer++ = 'r'; break;
33538fd1498Szrj 		  case CPP_AND_AND:
33638fd1498Szrj 		    strcpy ((char *) buffer, " and then ");
33738fd1498Szrj 		    buffer += 10;
33838fd1498Szrj 		    break;
33938fd1498Szrj 		  case CPP_OR_OR:
34038fd1498Szrj 		    strcpy ((char *) buffer, " or else ");
34138fd1498Szrj 		    buffer += 9;
34238fd1498Szrj 		    break;
34338fd1498Szrj 
34438fd1498Szrj 		  case CPP_PADDING:
34538fd1498Szrj 		    *buffer++ = ' ';
34638fd1498Szrj 		    is_one = prev_is_one;
34738fd1498Szrj 		    break;
34838fd1498Szrj 
34938fd1498Szrj 		  case CPP_COMMENT:
35038fd1498Szrj 		    break;
35138fd1498Szrj 
35238fd1498Szrj 		  case CPP_WSTRING:
35338fd1498Szrj 		  case CPP_STRING16:
35438fd1498Szrj 		  case CPP_STRING32:
35538fd1498Szrj 		  case CPP_UTF8STRING:
35638fd1498Szrj 		  case CPP_WCHAR:
35738fd1498Szrj 		  case CPP_CHAR16:
35838fd1498Szrj 		  case CPP_CHAR32:
35938fd1498Szrj 		  case CPP_UTF8CHAR:
36038fd1498Szrj 		  case CPP_NAME:
36138fd1498Szrj 		    if (!macro->fun_like)
36238fd1498Szrj 		      supported = 0;
36338fd1498Szrj 		    else
36438fd1498Szrj 		      buffer
36538fd1498Szrj 			= cpp_spell_token (parse_in, token, buffer, false);
36638fd1498Szrj 		    break;
36738fd1498Szrj 
36838fd1498Szrj 		  case CPP_STRING:
36938fd1498Szrj 		    if (is_string)
37038fd1498Szrj 		      {
37138fd1498Szrj 			*buffer++ = '&';
37238fd1498Szrj 			*buffer++ = ' ';
37338fd1498Szrj 		      }
37438fd1498Szrj 		    else
37538fd1498Szrj 		      is_string = 1;
37638fd1498Szrj 		    {
37738fd1498Szrj 		      const unsigned char *s = token->val.str.text;
37838fd1498Szrj 
37938fd1498Szrj 		      for (; *s; s++)
38038fd1498Szrj 			if (*s == '\\')
38138fd1498Szrj 			  {
38238fd1498Szrj 			    s++;
38338fd1498Szrj 			    buffer = handle_escape_character (buffer, *s);
38438fd1498Szrj 			    if (buffer == NULL)
38538fd1498Szrj 			      {
38638fd1498Szrj 				supported = 0;
38738fd1498Szrj 				break;
38838fd1498Szrj 			      }
38938fd1498Szrj 			  }
39038fd1498Szrj 			else
39138fd1498Szrj 			  *buffer++ = *s;
39238fd1498Szrj 		    }
39338fd1498Szrj 		    break;
39438fd1498Szrj 
39538fd1498Szrj 		  case CPP_CHAR:
39638fd1498Szrj 		    is_char = 1;
39738fd1498Szrj 		    {
39838fd1498Szrj 		      unsigned chars_seen;
39938fd1498Szrj 		      int ignored;
40038fd1498Szrj 		      cppchar_t c;
40138fd1498Szrj 
40238fd1498Szrj 		      c = cpp_interpret_charconst (parse_in, token,
40338fd1498Szrj 						   &chars_seen, &ignored);
40438fd1498Szrj 		      if (c >= 32 && c <= 126)
40538fd1498Szrj 			{
40638fd1498Szrj 			  *buffer++ = '\'';
40738fd1498Szrj 			  *buffer++ = (char) c;
40838fd1498Szrj 			  *buffer++ = '\'';
40938fd1498Szrj 			}
41038fd1498Szrj 		      else
41138fd1498Szrj 			{
41238fd1498Szrj 			  chars_seen = sprintf
41338fd1498Szrj 			    ((char *) buffer, "Character'Val (%d)", (int) c);
41438fd1498Szrj 			  buffer += chars_seen;
41538fd1498Szrj 			}
41638fd1498Szrj 		    }
41738fd1498Szrj 		    break;
41838fd1498Szrj 
41938fd1498Szrj 		  case CPP_NUMBER:
42038fd1498Szrj 		    tmp = cpp_token_as_text (parse_in, token);
42138fd1498Szrj 
42238fd1498Szrj 		    switch (*tmp)
42338fd1498Szrj 		      {
42438fd1498Szrj 			case '0':
42538fd1498Szrj 			  switch (tmp[1])
42638fd1498Szrj 			    {
42738fd1498Szrj 			      case '\0':
42838fd1498Szrj 			      case 'l':
42938fd1498Szrj 			      case 'L':
43038fd1498Szrj 			      case 'u':
43138fd1498Szrj 			      case 'U':
43238fd1498Szrj 				*buffer++ = '0';
43338fd1498Szrj 				break;
43438fd1498Szrj 
43538fd1498Szrj 			      case 'x':
43638fd1498Szrj 			      case 'X':
43738fd1498Szrj 				*buffer++ = '1';
43838fd1498Szrj 				*buffer++ = '6';
43938fd1498Szrj 				*buffer++ = '#';
44038fd1498Szrj 				buffer = dump_number (tmp + 2, buffer, false);
44138fd1498Szrj 				*buffer++ = '#';
44238fd1498Szrj 				break;
44338fd1498Szrj 
44438fd1498Szrj 			      case 'b':
44538fd1498Szrj 			      case 'B':
44638fd1498Szrj 				*buffer++ = '2';
44738fd1498Szrj 				*buffer++ = '#';
44838fd1498Szrj 				buffer = dump_number (tmp + 2, buffer, false);
44938fd1498Szrj 				*buffer++ = '#';
45038fd1498Szrj 				break;
45138fd1498Szrj 
45238fd1498Szrj 			      default:
45338fd1498Szrj 				/* Dump floating-point constant unmodified.  */
45438fd1498Szrj 				if (strchr ((const char *)tmp, '.'))
45538fd1498Szrj 				  buffer = dump_number (tmp, buffer, true);
45638fd1498Szrj 				else
45738fd1498Szrj 				  {
45838fd1498Szrj 				    *buffer++ = '8';
45938fd1498Szrj 				    *buffer++ = '#';
46038fd1498Szrj 				    buffer
46138fd1498Szrj 				      = dump_number (tmp + 1, buffer, false);
46238fd1498Szrj 				    *buffer++ = '#';
46338fd1498Szrj 				  }
46438fd1498Szrj 				break;
46538fd1498Szrj 			    }
46638fd1498Szrj 			  break;
46738fd1498Szrj 
46838fd1498Szrj 			case '1':
46938fd1498Szrj 			  if (tmp[1] == '\0'
47038fd1498Szrj 			      || tmp[1] == 'u'
47138fd1498Szrj 			      || tmp[1] == 'U'
47238fd1498Szrj 			      || tmp[1] == 'l'
47338fd1498Szrj 			      || tmp[1] == 'L')
47438fd1498Szrj 			    {
47538fd1498Szrj 			      is_one = 1;
47638fd1498Szrj 			      char_one = buffer;
47738fd1498Szrj 			      *buffer++ = '1';
47838fd1498Szrj 			      break;
47938fd1498Szrj 			    }
48038fd1498Szrj 			  /* fallthrough */
48138fd1498Szrj 
48238fd1498Szrj 			default:
48338fd1498Szrj 			  buffer
48438fd1498Szrj 			    = dump_number (tmp, buffer,
48538fd1498Szrj 					   strchr ((const char *)tmp, '.'));
48638fd1498Szrj 			  break;
48738fd1498Szrj 		      }
48838fd1498Szrj 		    break;
48938fd1498Szrj 
49038fd1498Szrj 		  case CPP_LSHIFT:
49138fd1498Szrj 		    if (prev_is_one)
49238fd1498Szrj 		      {
49338fd1498Szrj 			/* Replace "1 << N" by "2 ** N" */
49438fd1498Szrj 		        *char_one = '2';
49538fd1498Szrj 		        *buffer++ = '*';
49638fd1498Szrj 		        *buffer++ = '*';
49738fd1498Szrj 		        break;
49838fd1498Szrj 		      }
49938fd1498Szrj 		    /* fallthrough */
50038fd1498Szrj 
50138fd1498Szrj 		  case CPP_RSHIFT:
50238fd1498Szrj 		  case CPP_COMPL:
50338fd1498Szrj 		  case CPP_QUERY:
50438fd1498Szrj 		  case CPP_EOF:
50538fd1498Szrj 		  case CPP_PLUS_EQ:
50638fd1498Szrj 		  case CPP_MINUS_EQ:
50738fd1498Szrj 		  case CPP_MULT_EQ:
50838fd1498Szrj 		  case CPP_DIV_EQ:
50938fd1498Szrj 		  case CPP_MOD_EQ:
51038fd1498Szrj 		  case CPP_AND_EQ:
51138fd1498Szrj 		  case CPP_OR_EQ:
51238fd1498Szrj 		  case CPP_XOR_EQ:
51338fd1498Szrj 		  case CPP_RSHIFT_EQ:
51438fd1498Szrj 		  case CPP_LSHIFT_EQ:
51538fd1498Szrj 		  case CPP_PRAGMA:
51638fd1498Szrj 		  case CPP_PRAGMA_EOL:
51738fd1498Szrj 		  case CPP_HASH:
51838fd1498Szrj 		  case CPP_PASTE:
51938fd1498Szrj 		  case CPP_OPEN_BRACE:
52038fd1498Szrj 		  case CPP_CLOSE_BRACE:
52138fd1498Szrj 		  case CPP_SEMICOLON:
52238fd1498Szrj 		  case CPP_ELLIPSIS:
52338fd1498Szrj 		  case CPP_PLUS_PLUS:
52438fd1498Szrj 		  case CPP_MINUS_MINUS:
52538fd1498Szrj 		  case CPP_DEREF_STAR:
52638fd1498Szrj 		  case CPP_DOT_STAR:
52738fd1498Szrj 		  case CPP_ATSIGN:
52838fd1498Szrj 		  case CPP_HEADER_NAME:
52938fd1498Szrj 		  case CPP_AT_NAME:
53038fd1498Szrj 		  case CPP_OTHER:
53138fd1498Szrj 		  case CPP_OBJC_STRING:
53238fd1498Szrj 		  default:
53338fd1498Szrj 		    if (!macro->fun_like)
53438fd1498Szrj 		      supported = 0;
53538fd1498Szrj 		    else
53638fd1498Szrj 		      buffer = cpp_spell_token (parse_in, token, buffer, false);
53738fd1498Szrj 		    break;
53838fd1498Szrj 		}
53938fd1498Szrj 
54038fd1498Szrj 	      prev_is_one = is_one;
54138fd1498Szrj 	    }
54238fd1498Szrj 
54338fd1498Szrj 	  if (supported)
54438fd1498Szrj 	    *buffer = '\0';
54538fd1498Szrj 	}
54638fd1498Szrj 
54738fd1498Szrj       if (macro->fun_like && supported)
54838fd1498Szrj 	{
54938fd1498Szrj 	  char *start = (char *) s;
55038fd1498Szrj 	  int is_function = 0;
55138fd1498Szrj 
55238fd1498Szrj 	  pp_string (pp, "   --  arg-macro: ");
55338fd1498Szrj 
55438fd1498Szrj 	  if (*start == '(' && buffer[-1] == ')')
55538fd1498Szrj 	    {
55638fd1498Szrj 	      start++;
55738fd1498Szrj 	      buffer[-1] = '\0';
55838fd1498Szrj 	      is_function = 1;
55938fd1498Szrj 	      pp_string (pp, "function ");
56038fd1498Szrj 	    }
56138fd1498Szrj 	  else
56238fd1498Szrj 	    {
56338fd1498Szrj 	      pp_string (pp, "procedure ");
56438fd1498Szrj 	    }
56538fd1498Szrj 
56638fd1498Szrj 	  pp_string (pp, (const char *) NODE_NAME (node));
56738fd1498Szrj 	  pp_space (pp);
56838fd1498Szrj 	  pp_string (pp, (char *) params);
56938fd1498Szrj 	  pp_newline (pp);
57038fd1498Szrj 	  pp_string (pp, "   --    ");
57138fd1498Szrj 
57238fd1498Szrj 	  if (is_function)
57338fd1498Szrj 	    {
57438fd1498Szrj 	      pp_string (pp, "return ");
57538fd1498Szrj 	      pp_string (pp, start);
57638fd1498Szrj 	      pp_semicolon (pp);
57738fd1498Szrj 	    }
57838fd1498Szrj 	  else
57938fd1498Szrj 	    pp_string (pp, start);
58038fd1498Szrj 
58138fd1498Szrj 	  pp_newline (pp);
58238fd1498Szrj 	}
58338fd1498Szrj       else if (supported)
58438fd1498Szrj 	{
58538fd1498Szrj 	  expanded_location sloc = expand_location (macro->line);
58638fd1498Szrj 
58738fd1498Szrj 	  if (sloc.line != prev_line + 1 && prev_line > 0)
58838fd1498Szrj 	    pp_newline (pp);
58938fd1498Szrj 
59038fd1498Szrj 	  num_macros++;
59138fd1498Szrj 	  prev_line = sloc.line;
59238fd1498Szrj 
59338fd1498Szrj 	  pp_string (pp, "   ");
59438fd1498Szrj 	  ada_name = to_ada_name ((const char *) NODE_NAME (node), 0, NULL);
59538fd1498Szrj 	  pp_string (pp, ada_name);
59638fd1498Szrj 	  free (ada_name);
59738fd1498Szrj 	  pp_string (pp, " : ");
59838fd1498Szrj 
59938fd1498Szrj 	  if (is_string)
60038fd1498Szrj 	    pp_string (pp, "aliased constant String");
60138fd1498Szrj 	  else if (is_char)
60238fd1498Szrj 	    pp_string (pp, "aliased constant Character");
60338fd1498Szrj 	  else
60438fd1498Szrj 	    pp_string (pp, "constant");
60538fd1498Szrj 
60638fd1498Szrj 	  pp_string (pp, " := ");
60738fd1498Szrj 	  pp_string (pp, (char *) s);
60838fd1498Szrj 
60938fd1498Szrj 	  if (is_string)
61038fd1498Szrj 	    pp_string (pp, " & ASCII.NUL");
61138fd1498Szrj 
61238fd1498Szrj 	  pp_string (pp, ";  --  ");
61338fd1498Szrj 	  pp_string (pp, sloc.file);
61438fd1498Szrj 	  pp_colon (pp);
61538fd1498Szrj 	  pp_scalar (pp, "%d", sloc.line);
61638fd1498Szrj 	  pp_newline (pp);
61738fd1498Szrj 	}
61838fd1498Szrj       else
61938fd1498Szrj 	{
62038fd1498Szrj 	  pp_string (pp, "   --  unsupported macro: ");
62138fd1498Szrj 	  pp_string (pp, (const char *) cpp_macro_definition (parse_in, node));
62238fd1498Szrj 	  pp_newline (pp);
62338fd1498Szrj 	}
62438fd1498Szrj     }
62538fd1498Szrj 
62638fd1498Szrj   if (num_macros > 0)
62738fd1498Szrj     pp_newline (pp);
62838fd1498Szrj }
62938fd1498Szrj 
63038fd1498Szrj /* Current source file being handled.  */
63138fd1498Szrj static const char *current_source_file;
63238fd1498Szrj 
63338fd1498Szrj /* Return sloc of DECL, using sloc of last field if LAST is true.  */
63438fd1498Szrj 
63538fd1498Szrj location_t
decl_sloc(const_tree decl,bool last)63638fd1498Szrj decl_sloc (const_tree decl, bool last)
63738fd1498Szrj {
63838fd1498Szrj   tree field;
63938fd1498Szrj 
64038fd1498Szrj   /* Compare the declaration of struct-like types based on the sloc of their
64138fd1498Szrj      last field (if LAST is true), so that more nested types collate before
64238fd1498Szrj      less nested ones.  */
64338fd1498Szrj   if (TREE_CODE (decl) == TYPE_DECL
64438fd1498Szrj       && !DECL_ORIGINAL_TYPE (decl)
64538fd1498Szrj       && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
64638fd1498Szrj       && (field = TYPE_FIELDS (TREE_TYPE (decl))))
64738fd1498Szrj     {
64838fd1498Szrj       if (last)
64938fd1498Szrj 	while (DECL_CHAIN (field))
65038fd1498Szrj 	  field = DECL_CHAIN (field);
65138fd1498Szrj       return DECL_SOURCE_LOCATION (field);
65238fd1498Szrj     }
65338fd1498Szrj 
65438fd1498Szrj   return DECL_SOURCE_LOCATION (decl);
65538fd1498Szrj }
65638fd1498Szrj 
65738fd1498Szrj /* Compare two locations LHS and RHS.  */
65838fd1498Szrj 
65938fd1498Szrj static int
compare_location(location_t lhs,location_t rhs)66038fd1498Szrj compare_location (location_t lhs, location_t rhs)
66138fd1498Szrj {
66238fd1498Szrj   expanded_location xlhs = expand_location (lhs);
66338fd1498Szrj   expanded_location xrhs = expand_location (rhs);
66438fd1498Szrj 
66538fd1498Szrj   if (xlhs.file != xrhs.file)
66638fd1498Szrj     return filename_cmp (xlhs.file, xrhs.file);
66738fd1498Szrj 
66838fd1498Szrj   if (xlhs.line != xrhs.line)
66938fd1498Szrj     return xlhs.line - xrhs.line;
67038fd1498Szrj 
67138fd1498Szrj   if (xlhs.column != xrhs.column)
67238fd1498Szrj     return xlhs.column - xrhs.column;
67338fd1498Szrj 
67438fd1498Szrj   return 0;
67538fd1498Szrj }
67638fd1498Szrj 
67738fd1498Szrj /* Compare two declarations (LP and RP) by their source location.  */
67838fd1498Szrj 
67938fd1498Szrj static int
compare_node(const void * lp,const void * rp)68038fd1498Szrj compare_node (const void *lp, const void *rp)
68138fd1498Szrj {
68238fd1498Szrj   const_tree lhs = *((const tree *) lp);
68338fd1498Szrj   const_tree rhs = *((const tree *) rp);
68438fd1498Szrj 
68538fd1498Szrj   return compare_location (decl_sloc (lhs, true), decl_sloc (rhs, true));
68638fd1498Szrj }
68738fd1498Szrj 
68838fd1498Szrj /* Compare two comments (LP and RP) by their source location.  */
68938fd1498Szrj 
69038fd1498Szrj static int
compare_comment(const void * lp,const void * rp)69138fd1498Szrj compare_comment (const void *lp, const void *rp)
69238fd1498Szrj {
69338fd1498Szrj   const cpp_comment *lhs = (const cpp_comment *) lp;
69438fd1498Szrj   const cpp_comment *rhs = (const cpp_comment *) rp;
69538fd1498Szrj 
69638fd1498Szrj   return compare_location (lhs->sloc, rhs->sloc);
69738fd1498Szrj }
69838fd1498Szrj 
69938fd1498Szrj static tree *to_dump = NULL;
70038fd1498Szrj static int to_dump_count = 0;
70138fd1498Szrj 
70238fd1498Szrj /* Collect a list of declarations from T relevant to SOURCE_FILE to be dumped
70338fd1498Szrj    by a subsequent call to dump_ada_nodes.  */
70438fd1498Szrj 
70538fd1498Szrj void
collect_ada_nodes(tree t,const char * source_file)70638fd1498Szrj collect_ada_nodes (tree t, const char *source_file)
70738fd1498Szrj {
70838fd1498Szrj   tree n;
70938fd1498Szrj   int i = to_dump_count;
71038fd1498Szrj 
71138fd1498Szrj   /* Count the likely relevant nodes: do not dump builtins (they are irrelevant
71238fd1498Szrj      in the context of bindings) and namespaces (we do not handle them properly
71338fd1498Szrj      yet).  */
71438fd1498Szrj   for (n = t; n; n = TREE_CHAIN (n))
71538fd1498Szrj     if (!DECL_IS_BUILTIN (n)
71638fd1498Szrj 	&& TREE_CODE (n) != NAMESPACE_DECL
71738fd1498Szrj 	&& LOCATION_FILE (decl_sloc (n, false)) == source_file)
71838fd1498Szrj       to_dump_count++;
71938fd1498Szrj 
72038fd1498Szrj   /* Allocate sufficient storage for all nodes.  */
72138fd1498Szrj   to_dump = XRESIZEVEC (tree, to_dump, to_dump_count);
72238fd1498Szrj 
72338fd1498Szrj   /* Store the relevant nodes.  */
72438fd1498Szrj   for (n = t; n; n = TREE_CHAIN (n))
72538fd1498Szrj     if (!DECL_IS_BUILTIN (n)
72638fd1498Szrj 	&& TREE_CODE (n) != NAMESPACE_DECL
72738fd1498Szrj 	&& LOCATION_FILE (decl_sloc (n, false)) == source_file)
72838fd1498Szrj       to_dump[i++] = n;
72938fd1498Szrj }
73038fd1498Szrj 
73138fd1498Szrj /* Call back for walk_tree to clear the TREE_VISITED flag of TP.  */
73238fd1498Szrj 
73338fd1498Szrj static tree
unmark_visited_r(tree * tp,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)73438fd1498Szrj unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
73538fd1498Szrj 		  void *data ATTRIBUTE_UNUSED)
73638fd1498Szrj {
73738fd1498Szrj   if (TREE_VISITED (*tp))
73838fd1498Szrj     TREE_VISITED (*tp) = 0;
73938fd1498Szrj   else
74038fd1498Szrj     *walk_subtrees = 0;
74138fd1498Szrj 
74238fd1498Szrj   return NULL_TREE;
74338fd1498Szrj }
74438fd1498Szrj 
74538fd1498Szrj /* Print a COMMENT to the output stream PP.  */
74638fd1498Szrj 
74738fd1498Szrj static void
print_comment(pretty_printer * pp,const char * comment)74838fd1498Szrj print_comment (pretty_printer *pp, const char *comment)
74938fd1498Szrj {
75038fd1498Szrj   int len = strlen (comment);
75138fd1498Szrj   char *str = XALLOCAVEC (char, len + 1);
75238fd1498Szrj   char *tok;
75338fd1498Szrj   bool extra_newline = false;
75438fd1498Szrj 
75538fd1498Szrj   memcpy (str, comment, len + 1);
75638fd1498Szrj 
75738fd1498Szrj   /* Trim C/C++ comment indicators.  */
75838fd1498Szrj   if (str[len - 2] == '*' && str[len - 1] == '/')
75938fd1498Szrj     {
76038fd1498Szrj       str[len - 2] = ' ';
76138fd1498Szrj       str[len - 1] = '\0';
76238fd1498Szrj     }
76338fd1498Szrj   str += 2;
76438fd1498Szrj 
76538fd1498Szrj   tok = strtok (str, "\n");
76638fd1498Szrj   while (tok) {
76738fd1498Szrj     pp_string (pp, "  --");
76838fd1498Szrj     pp_string (pp, tok);
76938fd1498Szrj     pp_newline (pp);
77038fd1498Szrj     tok = strtok (NULL, "\n");
77138fd1498Szrj 
77238fd1498Szrj     /* Leave a blank line after multi-line comments.  */
77338fd1498Szrj     if (tok)
77438fd1498Szrj       extra_newline = true;
77538fd1498Szrj   }
77638fd1498Szrj 
77738fd1498Szrj   if (extra_newline)
77838fd1498Szrj     pp_newline (pp);
77938fd1498Szrj }
78038fd1498Szrj 
78138fd1498Szrj /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
78238fd1498Szrj    to collect_ada_nodes.  */
78338fd1498Szrj 
78438fd1498Szrj static void
dump_ada_nodes(pretty_printer * pp,const char * source_file)78538fd1498Szrj dump_ada_nodes (pretty_printer *pp, const char *source_file)
78638fd1498Szrj {
78738fd1498Szrj   int i, j;
78838fd1498Szrj   cpp_comment_table *comments;
78938fd1498Szrj 
79038fd1498Szrj   /* Sort the table of declarations to dump by sloc.  */
79138fd1498Szrj   qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
79238fd1498Szrj 
79338fd1498Szrj   /* Fetch the table of comments.  */
79438fd1498Szrj   comments = cpp_get_comments (parse_in);
79538fd1498Szrj 
79638fd1498Szrj   /* Sort the comments table by sloc.  */
79738fd1498Szrj   if (comments->count > 1)
79838fd1498Szrj     qsort (comments->entries, comments->count, sizeof (cpp_comment),
79938fd1498Szrj 	   compare_comment);
80038fd1498Szrj 
80138fd1498Szrj   /* Interleave comments and declarations in line number order.  */
80238fd1498Szrj   i = j = 0;
80338fd1498Szrj   do
80438fd1498Szrj     {
80538fd1498Szrj       /* Advance j until comment j is in this file.  */
80638fd1498Szrj       while (j != comments->count
80738fd1498Szrj 	     && LOCATION_FILE (comments->entries[j].sloc) != source_file)
80838fd1498Szrj 	j++;
80938fd1498Szrj 
81038fd1498Szrj       /* Advance j until comment j is not a duplicate.  */
81138fd1498Szrj       while (j < comments->count - 1
81238fd1498Szrj 	     && !compare_comment (&comments->entries[j],
81338fd1498Szrj 				  &comments->entries[j + 1]))
81438fd1498Szrj 	j++;
81538fd1498Szrj 
81638fd1498Szrj       /* Write decls until decl i collates after comment j.  */
81738fd1498Szrj       while (i != to_dump_count)
81838fd1498Szrj 	{
81938fd1498Szrj 	  if (j == comments->count
82038fd1498Szrj 	      || LOCATION_LINE (decl_sloc (to_dump[i], false))
82138fd1498Szrj 	      <  LOCATION_LINE (comments->entries[j].sloc))
82238fd1498Szrj 	    {
82338fd1498Szrj 	      current_source_file = source_file;
82438fd1498Szrj 
82538fd1498Szrj 	      if (dump_ada_declaration (pp, to_dump[i++], NULL_TREE,
82638fd1498Szrj 					 INDENT_INCR))
82738fd1498Szrj 		{
82838fd1498Szrj 		  pp_newline (pp);
82938fd1498Szrj 		  pp_newline (pp);
83038fd1498Szrj 		}
83138fd1498Szrj 	    }
83238fd1498Szrj 	  else
83338fd1498Szrj 	    break;
83438fd1498Szrj 	}
83538fd1498Szrj 
83638fd1498Szrj       /* Write comment j, if there is one.  */
83738fd1498Szrj       if (j != comments->count)
83838fd1498Szrj 	print_comment (pp, comments->entries[j++].comment);
83938fd1498Szrj 
84038fd1498Szrj     } while (i != to_dump_count || j != comments->count);
84138fd1498Szrj 
84238fd1498Szrj   /* Clear the TREE_VISITED flag over each subtree we've dumped.  */
84338fd1498Szrj   for (i = 0; i < to_dump_count; i++)
84438fd1498Szrj     walk_tree (&to_dump[i], unmark_visited_r, NULL, NULL);
84538fd1498Szrj 
84638fd1498Szrj   /* Finalize the to_dump table.  */
84738fd1498Szrj   if (to_dump)
84838fd1498Szrj     {
84938fd1498Szrj       free (to_dump);
85038fd1498Szrj       to_dump = NULL;
85138fd1498Szrj       to_dump_count = 0;
85238fd1498Szrj     }
85338fd1498Szrj }
85438fd1498Szrj 
85538fd1498Szrj /* Dump a newline and indent BUFFER by SPC chars.  */
85638fd1498Szrj 
85738fd1498Szrj static void
newline_and_indent(pretty_printer * buffer,int spc)85838fd1498Szrj newline_and_indent (pretty_printer *buffer, int spc)
85938fd1498Szrj {
86038fd1498Szrj   pp_newline (buffer);
86138fd1498Szrj   INDENT (spc);
86238fd1498Szrj }
86338fd1498Szrj 
86438fd1498Szrj struct with { char *s; const char *in_file; bool limited; };
86538fd1498Szrj static struct with *withs = NULL;
86638fd1498Szrj static int withs_max = 4096;
86738fd1498Szrj static int with_len = 0;
86838fd1498Szrj 
86938fd1498Szrj /* Record a "with" clause on package S (a limited with if LIMITED_ACCESS is
87038fd1498Szrj    true), if not already done.  */
87138fd1498Szrj 
87238fd1498Szrj static void
append_withs(const char * s,bool limited_access)87338fd1498Szrj append_withs (const char *s, bool limited_access)
87438fd1498Szrj {
87538fd1498Szrj   int i;
87638fd1498Szrj 
87738fd1498Szrj   if (withs == NULL)
87838fd1498Szrj     withs = XNEWVEC (struct with, withs_max);
87938fd1498Szrj 
88038fd1498Szrj   if (with_len == withs_max)
88138fd1498Szrj     {
88238fd1498Szrj       withs_max *= 2;
88338fd1498Szrj       withs = XRESIZEVEC (struct with, withs, withs_max);
88438fd1498Szrj     }
88538fd1498Szrj 
88638fd1498Szrj   for (i = 0; i < with_len; i++)
88738fd1498Szrj     if (!strcmp (s, withs[i].s)
88838fd1498Szrj 	&& current_source_file == withs[i].in_file)
88938fd1498Szrj       {
89038fd1498Szrj 	withs[i].limited &= limited_access;
89138fd1498Szrj 	return;
89238fd1498Szrj       }
89338fd1498Szrj 
89438fd1498Szrj   withs[with_len].s = xstrdup (s);
89538fd1498Szrj   withs[with_len].in_file = current_source_file;
89638fd1498Szrj   withs[with_len].limited = limited_access;
89738fd1498Szrj   with_len++;
89838fd1498Szrj }
89938fd1498Szrj 
90038fd1498Szrj /* Reset "with" clauses.  */
90138fd1498Szrj 
90238fd1498Szrj static void
reset_ada_withs(void)90338fd1498Szrj reset_ada_withs (void)
90438fd1498Szrj {
90538fd1498Szrj   int i;
90638fd1498Szrj 
90738fd1498Szrj   if (!withs)
90838fd1498Szrj     return;
90938fd1498Szrj 
91038fd1498Szrj   for (i = 0; i < with_len; i++)
91138fd1498Szrj     free (withs[i].s);
91238fd1498Szrj   free (withs);
91338fd1498Szrj   withs = NULL;
91438fd1498Szrj   withs_max = 4096;
91538fd1498Szrj   with_len = 0;
91638fd1498Szrj }
91738fd1498Szrj 
91838fd1498Szrj /* Dump "with" clauses in F.  */
91938fd1498Szrj 
92038fd1498Szrj static void
dump_ada_withs(FILE * f)92138fd1498Szrj dump_ada_withs (FILE *f)
92238fd1498Szrj {
92338fd1498Szrj   int i;
92438fd1498Szrj 
92538fd1498Szrj   fprintf (f, "with Interfaces.C; use Interfaces.C;\n");
92638fd1498Szrj 
92738fd1498Szrj   for (i = 0; i < with_len; i++)
92838fd1498Szrj     fprintf
92938fd1498Szrj       (f, "%swith %s;\n", withs[i].limited ? "limited " : "", withs[i].s);
93038fd1498Szrj }
93138fd1498Szrj 
93238fd1498Szrj /* Return suitable Ada package name from FILE.  */
93338fd1498Szrj 
93438fd1498Szrj static char *
get_ada_package(const char * file)93538fd1498Szrj get_ada_package (const char *file)
93638fd1498Szrj {
93738fd1498Szrj   const char *base;
93838fd1498Szrj   char *res;
93938fd1498Szrj   const char *s;
94038fd1498Szrj   int i;
94138fd1498Szrj   size_t plen;
94238fd1498Szrj 
94338fd1498Szrj   s = strstr (file, "/include/");
94438fd1498Szrj   if (s)
94538fd1498Szrj     base = s + 9;
94638fd1498Szrj   else
94738fd1498Szrj     base = lbasename (file);
94838fd1498Szrj 
94938fd1498Szrj   if (ada_specs_parent == NULL)
95038fd1498Szrj     plen = 0;
95138fd1498Szrj   else
95238fd1498Szrj     plen = strlen (ada_specs_parent) + 1;
95338fd1498Szrj 
95438fd1498Szrj   res = XNEWVEC (char, plen + strlen (base) + 1);
95538fd1498Szrj   if (ada_specs_parent != NULL) {
95638fd1498Szrj     strcpy (res, ada_specs_parent);
95738fd1498Szrj     res[plen - 1] = '.';
95838fd1498Szrj   }
95938fd1498Szrj 
96038fd1498Szrj   for (i = plen; *base; base++, i++)
96138fd1498Szrj     switch (*base)
96238fd1498Szrj       {
96338fd1498Szrj 	case '+':
96438fd1498Szrj 	  res[i] = 'p';
96538fd1498Szrj 	  break;
96638fd1498Szrj 
96738fd1498Szrj 	case '.':
96838fd1498Szrj 	case '-':
96938fd1498Szrj 	case '_':
97038fd1498Szrj 	case '/':
97138fd1498Szrj 	case '\\':
97238fd1498Szrj 	  res[i] = (i == 0 || res[i - 1] == '.' || res[i - 1] == '_') ? 'u' : '_';
97338fd1498Szrj 	  break;
97438fd1498Szrj 
97538fd1498Szrj 	default:
97638fd1498Szrj 	  res[i] = *base;
97738fd1498Szrj 	  break;
97838fd1498Szrj       }
97938fd1498Szrj   res[i] = '\0';
98038fd1498Szrj 
98138fd1498Szrj   return res;
98238fd1498Szrj }
98338fd1498Szrj 
98438fd1498Szrj static const char *ada_reserved[] = {
98538fd1498Szrj   "abort", "abs", "abstract", "accept", "access", "aliased", "all", "and",
98638fd1498Szrj   "array", "at", "begin", "body", "case", "constant", "declare", "delay",
98738fd1498Szrj   "delta", "digits", "do", "else", "elsif", "end", "entry", "exception",
98838fd1498Szrj   "exit", "for", "function", "generic", "goto", "if", "in", "interface", "is",
98938fd1498Szrj   "limited", "loop", "mod", "new", "not", "null", "others", "out", "of", "or",
99038fd1498Szrj   "overriding", "package", "pragma", "private", "procedure", "protected",
99138fd1498Szrj   "raise", "range", "record", "rem", "renames", "requeue", "return", "reverse",
99238fd1498Szrj   "select", "separate", "subtype", "synchronized", "tagged", "task",
99338fd1498Szrj   "terminate", "then", "type", "until", "use", "when", "while", "with", "xor",
99438fd1498Szrj   NULL};
99538fd1498Szrj 
99638fd1498Szrj /* ??? would be nice to specify this list via a config file, so that users
99738fd1498Szrj    can create their own dictionary of conflicts.  */
99838fd1498Szrj static const char *c_duplicates[] = {
99938fd1498Szrj   /* system will cause troubles with System.Address.  */
100038fd1498Szrj   "system",
100138fd1498Szrj 
100238fd1498Szrj   /* The following values have other definitions with same name/other
100338fd1498Szrj      casing.  */
100438fd1498Szrj   "funmap",
100538fd1498Szrj   "rl_vi_fWord",
100638fd1498Szrj   "rl_vi_bWord",
100738fd1498Szrj   "rl_vi_eWord",
100838fd1498Szrj   "rl_readline_version",
100938fd1498Szrj   "_Vx_ushort",
101038fd1498Szrj   "USHORT",
101138fd1498Szrj   "XLookupKeysym",
101238fd1498Szrj   NULL};
101338fd1498Szrj 
101438fd1498Szrj /* Return a declaration tree corresponding to TYPE.  */
101538fd1498Szrj 
101638fd1498Szrj static tree
get_underlying_decl(tree type)101738fd1498Szrj get_underlying_decl (tree type)
101838fd1498Szrj {
101938fd1498Szrj   if (!type)
102038fd1498Szrj     return NULL_TREE;
102138fd1498Szrj 
102238fd1498Szrj   /* type is a declaration.  */
102338fd1498Szrj   if (DECL_P (type))
102438fd1498Szrj     return type;
102538fd1498Szrj 
102638fd1498Szrj   /* type is a typedef.  */
102738fd1498Szrj   if (TYPE_P (type) && TYPE_NAME (type) && DECL_P (TYPE_NAME (type)))
102838fd1498Szrj     return TYPE_NAME (type);
102938fd1498Szrj 
103038fd1498Szrj   /* TYPE_STUB_DECL has been set for type.  */
103138fd1498Szrj   if (TYPE_P (type) && TYPE_STUB_DECL (type))
103238fd1498Szrj     return TYPE_STUB_DECL (type);
103338fd1498Szrj 
103438fd1498Szrj   return NULL_TREE;
103538fd1498Szrj }
103638fd1498Szrj 
103738fd1498Szrj /* Return whether TYPE has static fields.  */
103838fd1498Szrj 
103938fd1498Szrj static bool
has_static_fields(const_tree type)104038fd1498Szrj has_static_fields (const_tree type)
104138fd1498Szrj {
104238fd1498Szrj   if (!type || !RECORD_OR_UNION_TYPE_P (type))
104338fd1498Szrj     return false;
104438fd1498Szrj 
104538fd1498Szrj   for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
104638fd1498Szrj     if (TREE_CODE (fld) == VAR_DECL && DECL_NAME (fld))
104738fd1498Szrj       return true;
104838fd1498Szrj 
104938fd1498Szrj   return false;
105038fd1498Szrj }
105138fd1498Szrj 
105238fd1498Szrj /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
105338fd1498Szrj    table).  */
105438fd1498Szrj 
105538fd1498Szrj static bool
is_tagged_type(const_tree type)105638fd1498Szrj is_tagged_type (const_tree type)
105738fd1498Szrj {
105838fd1498Szrj   if (!type || !RECORD_OR_UNION_TYPE_P (type))
105938fd1498Szrj     return false;
106038fd1498Szrj 
106138fd1498Szrj   for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
106238fd1498Szrj     if (TREE_CODE (fld) == FUNCTION_DECL && DECL_VINDEX (fld))
106338fd1498Szrj       return true;
106438fd1498Szrj 
106538fd1498Szrj   return false;
106638fd1498Szrj }
106738fd1498Szrj 
106838fd1498Szrj /* Return whether TYPE has non-trivial methods, i.e. methods that do something
106938fd1498Szrj    for the objects of TYPE.  In C++, all classes have implicit special methods,
107038fd1498Szrj    e.g. constructors and destructors, but they can be trivial if the type is
107138fd1498Szrj    sufficiently simple.  */
107238fd1498Szrj 
107338fd1498Szrj static bool
has_nontrivial_methods(tree type)107438fd1498Szrj has_nontrivial_methods (tree type)
107538fd1498Szrj {
107638fd1498Szrj   if (!type || !RECORD_OR_UNION_TYPE_P (type))
107738fd1498Szrj     return false;
107838fd1498Szrj 
107938fd1498Szrj   /* Only C++ types can have methods.  */
108038fd1498Szrj   if (!cpp_check)
108138fd1498Szrj     return false;
108238fd1498Szrj 
108338fd1498Szrj   /* A non-trivial type has non-trivial special methods.  */
108438fd1498Szrj   if (!cpp_check (type, IS_TRIVIAL))
108538fd1498Szrj     return true;
108638fd1498Szrj 
108738fd1498Szrj   /* If there are user-defined methods, they are deemed non-trivial.  */
108838fd1498Szrj   for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
108938fd1498Szrj     if (TREE_CODE (fld) == FUNCTION_DECL && !DECL_ARTIFICIAL (fld))
109038fd1498Szrj       return true;
109138fd1498Szrj 
109238fd1498Szrj   return false;
109338fd1498Szrj }
109438fd1498Szrj 
109538fd1498Szrj #define INDEX_LENGTH 8
109638fd1498Szrj 
109738fd1498Szrj /* Generate a legal Ada name from a C/C++ NAME and return a malloc'ed string.
109838fd1498Szrj    INDEX, if non-zero, is used to disambiguate overloaded names.  SPACE_FOUND,
109938fd1498Szrj    if not NULL, is used to indicate whether a space was found in NAME.  */
110038fd1498Szrj 
110138fd1498Szrj static char *
to_ada_name(const char * name,unsigned int index,bool * space_found)110238fd1498Szrj to_ada_name (const char *name, unsigned int index, bool *space_found)
110338fd1498Szrj {
110438fd1498Szrj   const char **names;
110538fd1498Szrj   const int len = strlen (name);
110638fd1498Szrj   int j, len2 = 0;
110738fd1498Szrj   bool found = false;
110838fd1498Szrj   char *s = XNEWVEC (char, len * 2 + 5 + (index ? INDEX_LENGTH : 0));
110938fd1498Szrj   char c;
111038fd1498Szrj 
111138fd1498Szrj   if (space_found)
111238fd1498Szrj     *space_found = false;
111338fd1498Szrj 
111438fd1498Szrj   /* Add "c_" prefix if name is an Ada reserved word.  */
111538fd1498Szrj   for (names = ada_reserved; *names; names++)
111638fd1498Szrj     if (!strcasecmp (name, *names))
111738fd1498Szrj       {
111838fd1498Szrj 	s[len2++] = 'c';
111938fd1498Szrj 	s[len2++] = '_';
112038fd1498Szrj 	found = true;
112138fd1498Szrj 	break;
112238fd1498Szrj       }
112338fd1498Szrj 
112438fd1498Szrj   if (!found)
112538fd1498Szrj     /* Add "c_" prefix if name is a potential case sensitive duplicate.  */
112638fd1498Szrj     for (names = c_duplicates; *names; names++)
112738fd1498Szrj       if (!strcmp (name, *names))
112838fd1498Szrj 	{
112938fd1498Szrj 	  s[len2++] = 'c';
113038fd1498Szrj 	  s[len2++] = '_';
113138fd1498Szrj 	  found = true;
113238fd1498Szrj 	  break;
113338fd1498Szrj 	}
113438fd1498Szrj 
113538fd1498Szrj   for (j = 0; name[j] == '_'; j++)
113638fd1498Szrj     s[len2++] = 'u';
113738fd1498Szrj 
113838fd1498Szrj   if (j > 0)
113938fd1498Szrj     s[len2++] = '_';
114038fd1498Szrj   else if (*name == '.' || *name == '$')
114138fd1498Szrj     {
114238fd1498Szrj       s[0] = 'a';
114338fd1498Szrj       s[1] = 'n';
114438fd1498Szrj       s[2] = 'o';
114538fd1498Szrj       s[3] = 'n';
114638fd1498Szrj       len2 = 4;
114738fd1498Szrj       j++;
114838fd1498Szrj     }
114938fd1498Szrj 
115038fd1498Szrj   /* Replace unsuitable characters for Ada identifiers.  */
115138fd1498Szrj   for (; j < len; j++)
115238fd1498Szrj     switch (name[j])
115338fd1498Szrj       {
115438fd1498Szrj 	case ' ':
115538fd1498Szrj 	  if (space_found)
115638fd1498Szrj 	    *space_found = true;
115738fd1498Szrj 	  s[len2++] = '_';
115838fd1498Szrj 	  break;
115938fd1498Szrj 
116038fd1498Szrj 	/* ??? missing some C++ operators.  */
116138fd1498Szrj 	case '=':
116238fd1498Szrj 	  s[len2++] = '_';
116338fd1498Szrj 
116438fd1498Szrj 	  if (name[j + 1] == '=')
116538fd1498Szrj 	    {
116638fd1498Szrj 	      j++;
116738fd1498Szrj 	      s[len2++] = 'e';
116838fd1498Szrj 	      s[len2++] = 'q';
116938fd1498Szrj 	    }
117038fd1498Szrj 	  else
117138fd1498Szrj 	    {
117238fd1498Szrj 	      s[len2++] = 'a';
117338fd1498Szrj 	      s[len2++] = 's';
117438fd1498Szrj 	    }
117538fd1498Szrj 	  break;
117638fd1498Szrj 
117738fd1498Szrj 	case '!':
117838fd1498Szrj 	  s[len2++] = '_';
117938fd1498Szrj 	  if (name[j + 1] == '=')
118038fd1498Szrj 	    {
118138fd1498Szrj 	      j++;
118238fd1498Szrj 	      s[len2++] = 'n';
118338fd1498Szrj 	      s[len2++] = 'e';
118438fd1498Szrj 	    }
118538fd1498Szrj 	  break;
118638fd1498Szrj 
118738fd1498Szrj 	case '~':
118838fd1498Szrj 	  s[len2++] = '_';
118938fd1498Szrj 	  s[len2++] = 't';
119038fd1498Szrj 	  s[len2++] = 'i';
119138fd1498Szrj 	  break;
119238fd1498Szrj 
119338fd1498Szrj 	case '&':
119438fd1498Szrj 	case '|':
119538fd1498Szrj 	case '^':
119638fd1498Szrj 	  s[len2++] = '_';
119738fd1498Szrj 	  s[len2++] = name[j] == '&' ? 'a' : name[j] == '|' ? 'o' : 'x';
119838fd1498Szrj 
119938fd1498Szrj 	  if (name[j + 1] == '=')
120038fd1498Szrj 	    {
120138fd1498Szrj 	      j++;
120238fd1498Szrj 	      s[len2++] = 'e';
120338fd1498Szrj 	    }
120438fd1498Szrj 	  break;
120538fd1498Szrj 
120638fd1498Szrj 	case '+':
120738fd1498Szrj 	case '-':
120838fd1498Szrj 	case '*':
120938fd1498Szrj 	case '/':
121038fd1498Szrj 	case '(':
121138fd1498Szrj 	case '[':
121238fd1498Szrj 	  if (s[len2 - 1] != '_')
121338fd1498Szrj 	    s[len2++] = '_';
121438fd1498Szrj 
121538fd1498Szrj 	  switch (name[j + 1]) {
121638fd1498Szrj 	    case '\0':
121738fd1498Szrj 	      j++;
121838fd1498Szrj 	      switch (name[j - 1]) {
121938fd1498Szrj 		case '+': s[len2++] = 'p'; break;  /* + */
122038fd1498Szrj 		case '-': s[len2++] = 'm'; break;  /* - */
122138fd1498Szrj 		case '*': s[len2++] = 't'; break;  /* * */
122238fd1498Szrj 		case '/': s[len2++] = 'd'; break;  /* / */
122338fd1498Szrj 	      }
122438fd1498Szrj 	      break;
122538fd1498Szrj 
122638fd1498Szrj 	    case '=':
122738fd1498Szrj 	      j++;
122838fd1498Szrj 	      switch (name[j - 1]) {
122938fd1498Szrj 		case '+': s[len2++] = 'p'; break;  /* += */
123038fd1498Szrj 		case '-': s[len2++] = 'm'; break;  /* -= */
123138fd1498Szrj 		case '*': s[len2++] = 't'; break;  /* *= */
123238fd1498Szrj 		case '/': s[len2++] = 'd'; break;  /* /= */
123338fd1498Szrj 	      }
123438fd1498Szrj 	      s[len2++] = 'a';
123538fd1498Szrj 	      break;
123638fd1498Szrj 
123738fd1498Szrj 	    case '-':  /* -- */
123838fd1498Szrj 	      j++;
123938fd1498Szrj 	      s[len2++] = 'm';
124038fd1498Szrj 	      s[len2++] = 'm';
124138fd1498Szrj 	      break;
124238fd1498Szrj 
124338fd1498Szrj 	    case '+':  /* ++ */
124438fd1498Szrj 	      j++;
124538fd1498Szrj 	      s[len2++] = 'p';
124638fd1498Szrj 	      s[len2++] = 'p';
124738fd1498Szrj 	      break;
124838fd1498Szrj 
124938fd1498Szrj 	    case ')':  /* () */
125038fd1498Szrj 	      j++;
125138fd1498Szrj 	      s[len2++] = 'o';
125238fd1498Szrj 	      s[len2++] = 'p';
125338fd1498Szrj 	      break;
125438fd1498Szrj 
125538fd1498Szrj 	    case ']':  /* [] */
125638fd1498Szrj 	      j++;
125738fd1498Szrj 	      s[len2++] = 'o';
125838fd1498Szrj 	      s[len2++] = 'b';
125938fd1498Szrj 	      break;
126038fd1498Szrj 	  }
126138fd1498Szrj 
126238fd1498Szrj 	  break;
126338fd1498Szrj 
126438fd1498Szrj 	case '<':
126538fd1498Szrj 	case '>':
126638fd1498Szrj 	  c = name[j] == '<' ? 'l' : 'g';
126738fd1498Szrj 	  s[len2++] = '_';
126838fd1498Szrj 
126938fd1498Szrj 	  switch (name[j + 1]) {
127038fd1498Szrj 	    case '\0':
127138fd1498Szrj 	      s[len2++] = c;
127238fd1498Szrj 	      s[len2++] = 't';
127338fd1498Szrj 	      break;
127438fd1498Szrj 	    case '=':
127538fd1498Szrj 	      j++;
127638fd1498Szrj 	      s[len2++] = c;
127738fd1498Szrj 	      s[len2++] = 'e';
127838fd1498Szrj 	      break;
127938fd1498Szrj 	    case '>':
128038fd1498Szrj 	      j++;
128138fd1498Szrj 	      s[len2++] = 's';
128238fd1498Szrj 	      s[len2++] = 'r';
128338fd1498Szrj 	      break;
128438fd1498Szrj 	    case '<':
128538fd1498Szrj 	      j++;
128638fd1498Szrj 	      s[len2++] = 's';
128738fd1498Szrj 	      s[len2++] = 'l';
128838fd1498Szrj 	      break;
128938fd1498Szrj 	    default:
129038fd1498Szrj 	      break;
129138fd1498Szrj 	  }
129238fd1498Szrj 	  break;
129338fd1498Szrj 
129438fd1498Szrj 	case '_':
129538fd1498Szrj 	  if (len2 && s[len2 - 1] == '_')
129638fd1498Szrj 	    s[len2++] = 'u';
129738fd1498Szrj 	  /* fall through */
129838fd1498Szrj 
129938fd1498Szrj 	default:
130038fd1498Szrj 	  s[len2++] = name[j];
130138fd1498Szrj       }
130238fd1498Szrj 
130338fd1498Szrj   if (s[len2 - 1] == '_')
130438fd1498Szrj     s[len2++] = 'u';
130538fd1498Szrj 
130638fd1498Szrj   if (index)
130738fd1498Szrj     snprintf (&s[len2], INDEX_LENGTH, "_u_%d", index + 1);
130838fd1498Szrj   else
130938fd1498Szrj     s[len2] = '\0';
131038fd1498Szrj 
131138fd1498Szrj   return s;
131238fd1498Szrj }
131338fd1498Szrj 
131438fd1498Szrj /* Return true if DECL refers to a C++ class type for which a
131538fd1498Szrj    separate enclosing package has been or should be generated.  */
131638fd1498Szrj 
131738fd1498Szrj static bool
separate_class_package(tree decl)131838fd1498Szrj separate_class_package (tree decl)
131938fd1498Szrj {
132038fd1498Szrj   tree type = TREE_TYPE (decl);
132138fd1498Szrj   return has_nontrivial_methods (type) || has_static_fields (type);
132238fd1498Szrj }
132338fd1498Szrj 
132438fd1498Szrj static bool package_prefix = true;
132538fd1498Szrj 
132638fd1498Szrj /* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
132738fd1498Szrj    syntax.  INDEX, if non-zero, is used to disambiguate overloaded names.
132838fd1498Szrj    LIMITED_ACCESS indicates whether NODE can be accessed via a limited
132938fd1498Szrj    'with' clause rather than a regular 'with' clause.  */
133038fd1498Szrj 
133138fd1498Szrj static void
pp_ada_tree_identifier(pretty_printer * buffer,tree node,tree type,unsigned int index,bool limited_access)133238fd1498Szrj pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
133338fd1498Szrj 			unsigned int index, bool limited_access)
133438fd1498Szrj {
133538fd1498Szrj   const char *name = IDENTIFIER_POINTER (node);
133638fd1498Szrj   bool space_found = false;
133738fd1498Szrj   char *s = to_ada_name (name, index, &space_found);
133838fd1498Szrj   tree decl = get_underlying_decl (type);
133938fd1498Szrj 
134038fd1498Szrj   /* If the entity comes from another file, generate a package prefix.  */
134138fd1498Szrj   if (decl)
134238fd1498Szrj     {
134338fd1498Szrj       expanded_location xloc = expand_location (decl_sloc (decl, false));
134438fd1498Szrj 
134538fd1498Szrj       if (xloc.file && xloc.line)
134638fd1498Szrj 	{
134738fd1498Szrj 	  if (xloc.file != current_source_file)
134838fd1498Szrj 	    {
134938fd1498Szrj 	      switch (TREE_CODE (type))
135038fd1498Szrj 		{
135138fd1498Szrj 		  case ENUMERAL_TYPE:
135238fd1498Szrj 		  case INTEGER_TYPE:
135338fd1498Szrj 		  case REAL_TYPE:
135438fd1498Szrj 		  case FIXED_POINT_TYPE:
135538fd1498Szrj 		  case BOOLEAN_TYPE:
135638fd1498Szrj 		  case REFERENCE_TYPE:
135738fd1498Szrj 		  case POINTER_TYPE:
135838fd1498Szrj 		  case ARRAY_TYPE:
135938fd1498Szrj 		  case RECORD_TYPE:
136038fd1498Szrj 		  case UNION_TYPE:
136138fd1498Szrj 		  case TYPE_DECL:
136238fd1498Szrj 		    if (package_prefix)
136338fd1498Szrj 		      {
136438fd1498Szrj 			char *s1 = get_ada_package (xloc.file);
136538fd1498Szrj 			append_withs (s1, limited_access);
136638fd1498Szrj 			pp_string (buffer, s1);
136738fd1498Szrj 			pp_dot (buffer);
136838fd1498Szrj 			free (s1);
136938fd1498Szrj 		      }
137038fd1498Szrj 		    break;
137138fd1498Szrj 		  default:
137238fd1498Szrj 		    break;
137338fd1498Szrj 		}
137438fd1498Szrj 
137538fd1498Szrj 	      /* Generate the additional package prefix for C++ classes.  */
137638fd1498Szrj 	      if (separate_class_package (decl))
137738fd1498Szrj 		{
137838fd1498Szrj 		  pp_string (buffer, "Class_");
137938fd1498Szrj 		  pp_string (buffer, s);
138038fd1498Szrj 		  pp_dot (buffer);
138138fd1498Szrj 		}
138238fd1498Szrj 	     }
138338fd1498Szrj 	}
138438fd1498Szrj     }
138538fd1498Szrj 
138638fd1498Szrj   if (space_found)
138738fd1498Szrj     if (!strcmp (s, "short_int"))
138838fd1498Szrj       pp_string (buffer, "short");
138938fd1498Szrj     else if (!strcmp (s, "short_unsigned_int"))
139038fd1498Szrj       pp_string (buffer, "unsigned_short");
139138fd1498Szrj     else if (!strcmp (s, "unsigned_int"))
139238fd1498Szrj       pp_string (buffer, "unsigned");
139338fd1498Szrj     else if (!strcmp (s, "long_int"))
139438fd1498Szrj       pp_string (buffer, "long");
139538fd1498Szrj     else if (!strcmp (s, "long_unsigned_int"))
139638fd1498Szrj       pp_string (buffer, "unsigned_long");
139738fd1498Szrj     else if (!strcmp (s, "long_long_int"))
139838fd1498Szrj       pp_string (buffer, "Long_Long_Integer");
139938fd1498Szrj     else if (!strcmp (s, "long_long_unsigned_int"))
140038fd1498Szrj       {
140138fd1498Szrj 	if (package_prefix)
140238fd1498Szrj 	  {
140338fd1498Szrj 	    append_withs ("Interfaces.C.Extensions", false);
140438fd1498Szrj 	    pp_string (buffer, "Extensions.unsigned_long_long");
140538fd1498Szrj 	  }
140638fd1498Szrj 	else
140738fd1498Szrj 	  pp_string (buffer, "unsigned_long_long");
140838fd1498Szrj       }
140938fd1498Szrj     else
141038fd1498Szrj       pp_string(buffer, s);
141138fd1498Szrj   else
141238fd1498Szrj     if (!strcmp (s, "u_Bool") || !strcmp (s, "bool"))
141338fd1498Szrj       {
141438fd1498Szrj 	if (package_prefix)
141538fd1498Szrj 	  {
141638fd1498Szrj 	    append_withs ("Interfaces.C.Extensions", false);
141738fd1498Szrj 	    pp_string (buffer, "Extensions.bool");
141838fd1498Szrj 	  }
141938fd1498Szrj 	else
142038fd1498Szrj 	  pp_string (buffer, "bool");
142138fd1498Szrj       }
142238fd1498Szrj     else
142338fd1498Szrj       pp_string(buffer, s);
142438fd1498Szrj 
142538fd1498Szrj   free (s);
142638fd1498Szrj }
142738fd1498Szrj 
142838fd1498Szrj /* Dump in BUFFER the assembly name of T.  */
142938fd1498Szrj 
143038fd1498Szrj static void
pp_asm_name(pretty_printer * buffer,tree t)143138fd1498Szrj pp_asm_name (pretty_printer *buffer, tree t)
143238fd1498Szrj {
143338fd1498Szrj   tree name = DECL_ASSEMBLER_NAME (t);
143438fd1498Szrj   char *ada_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (name) + 1), *s;
143538fd1498Szrj   const char *ident = IDENTIFIER_POINTER (name);
143638fd1498Szrj 
143738fd1498Szrj   for (s = ada_name; *ident; ident++)
143838fd1498Szrj     {
143938fd1498Szrj       if (*ident == ' ')
144038fd1498Szrj 	break;
144138fd1498Szrj       else if (*ident != '*')
144238fd1498Szrj 	*s++ = *ident;
144338fd1498Szrj     }
144438fd1498Szrj 
144538fd1498Szrj   *s = '\0';
144638fd1498Szrj   pp_string (buffer, ada_name);
144738fd1498Szrj }
144838fd1498Szrj 
144938fd1498Szrj /* Hash table of overloaded names associating identifier nodes with DECL_UIDs.
145038fd1498Szrj    It is needed in Ada 2005 because we can have at most one import directive
145138fd1498Szrj    per subprogram name in a given scope, so we have to mangle the subprogram
145238fd1498Szrj    names on the Ada side to import overloaded subprograms from C++.  */
145338fd1498Szrj 
145438fd1498Szrj struct overloaded_name_hash {
145538fd1498Szrj   hashval_t hash;
145638fd1498Szrj   tree name;
145738fd1498Szrj   tree context;
145838fd1498Szrj   vec<unsigned int> homonyms;
145938fd1498Szrj };
146038fd1498Szrj 
146138fd1498Szrj struct overloaded_name_hasher : delete_ptr_hash<overloaded_name_hash>
146238fd1498Szrj {
hashoverloaded_name_hasher146338fd1498Szrj   static inline hashval_t hash (overloaded_name_hash *t)
146438fd1498Szrj     { return t->hash; }
equaloverloaded_name_hasher146538fd1498Szrj   static inline bool equal (overloaded_name_hash *a, overloaded_name_hash *b)
146638fd1498Szrj     { return a->name == b->name && a->context == b->context; }
146738fd1498Szrj };
146838fd1498Szrj 
146938fd1498Szrj static hash_table<overloaded_name_hasher> *overloaded_names;
147038fd1498Szrj 
147138fd1498Szrj /* Compute the overloading index of function DECL in its context.  */
147238fd1498Szrj 
147338fd1498Szrj static unsigned int
compute_overloading_index(tree decl)147438fd1498Szrj compute_overloading_index (tree decl)
147538fd1498Szrj {
147638fd1498Szrj   const hashval_t hashcode
147738fd1498Szrj     = iterative_hash_hashval_t (htab_hash_pointer (DECL_NAME (decl)),
147838fd1498Szrj 			        htab_hash_pointer (DECL_CONTEXT (decl)));
147938fd1498Szrj   struct overloaded_name_hash in, *h, **slot;
148038fd1498Szrj   unsigned int index, *iter;
148138fd1498Szrj 
148238fd1498Szrj   if (!overloaded_names)
148338fd1498Szrj     overloaded_names = new hash_table<overloaded_name_hasher> (512);
148438fd1498Szrj 
148538fd1498Szrj   /* Look up the list of homonyms in the table.  */
148638fd1498Szrj   in.hash = hashcode;
148738fd1498Szrj   in.name = DECL_NAME (decl);
148838fd1498Szrj   in.context = DECL_CONTEXT (decl);
148938fd1498Szrj   slot = overloaded_names->find_slot_with_hash (&in, hashcode, INSERT);
149038fd1498Szrj   if (*slot)
149138fd1498Szrj     h = *slot;
149238fd1498Szrj   else
149338fd1498Szrj     {
149438fd1498Szrj       h = new overloaded_name_hash;
149538fd1498Szrj       h->hash = hashcode;
149638fd1498Szrj       h->name = DECL_NAME (decl);
149738fd1498Szrj       h->context = DECL_CONTEXT (decl);
149838fd1498Szrj       h->homonyms.create (0);
149938fd1498Szrj       *slot = h;
150038fd1498Szrj     }
150138fd1498Szrj 
150238fd1498Szrj   /* Look up the function in the list of homonyms.  */
150338fd1498Szrj   FOR_EACH_VEC_ELT (h->homonyms, index, iter)
150438fd1498Szrj     if (*iter == DECL_UID (decl))
150538fd1498Szrj       break;
150638fd1498Szrj 
150738fd1498Szrj   /* If it is not present, push it onto the list.  */
150838fd1498Szrj   if (!iter)
150938fd1498Szrj     h->homonyms.safe_push (DECL_UID (decl));
151038fd1498Szrj 
151138fd1498Szrj   return index;
151238fd1498Szrj }
151338fd1498Szrj 
151438fd1498Szrj /* Dump in BUFFER the name of a DECL node if set, in Ada syntax.
151538fd1498Szrj    LIMITED_ACCESS indicates whether NODE can be accessed via a
151638fd1498Szrj    limited 'with' clause rather than a regular 'with' clause.  */
151738fd1498Szrj 
151838fd1498Szrj static void
dump_ada_decl_name(pretty_printer * buffer,tree decl,bool limited_access)151938fd1498Szrj dump_ada_decl_name (pretty_printer *buffer, tree decl, bool limited_access)
152038fd1498Szrj {
152138fd1498Szrj   if (DECL_NAME (decl))
152238fd1498Szrj     {
152338fd1498Szrj       const unsigned int index
152438fd1498Szrj 	= (TREE_CODE (decl) == FUNCTION_DECL && cpp_check)
152538fd1498Szrj 	  ? compute_overloading_index (decl) : 0;
152638fd1498Szrj       pp_ada_tree_identifier (buffer, DECL_NAME (decl), decl, index,
152738fd1498Szrj 			      limited_access);
152838fd1498Szrj     }
152938fd1498Szrj   else
153038fd1498Szrj     {
153138fd1498Szrj       tree type_name = TYPE_NAME (TREE_TYPE (decl));
153238fd1498Szrj 
153338fd1498Szrj       if (!type_name)
153438fd1498Szrj 	{
153538fd1498Szrj 	  pp_string (buffer, "anon");
153638fd1498Szrj 	  if (TREE_CODE (decl) == FIELD_DECL)
153738fd1498Szrj 	    pp_scalar (buffer, "%d", DECL_UID (decl));
153838fd1498Szrj 	  else
153938fd1498Szrj 	    pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (decl)));
154038fd1498Szrj 	}
154138fd1498Szrj       else if (TREE_CODE (type_name) == IDENTIFIER_NODE)
154238fd1498Szrj 	pp_ada_tree_identifier (buffer, type_name, decl, 0, limited_access);
154338fd1498Szrj     }
154438fd1498Szrj }
154538fd1498Szrj 
154638fd1498Szrj /* Dump in BUFFER a name based on both T1 and T2 followed by a suffix.  */
154738fd1498Szrj 
154838fd1498Szrj static void
dump_ada_double_name(pretty_printer * buffer,tree t1,tree t2)154938fd1498Szrj dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2)
155038fd1498Szrj {
155138fd1498Szrj   if (DECL_NAME (t1))
155238fd1498Szrj     pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, 0, false);
155338fd1498Szrj   else
155438fd1498Szrj     {
155538fd1498Szrj       pp_string (buffer, "anon");
155638fd1498Szrj       pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t1)));
155738fd1498Szrj     }
155838fd1498Szrj 
155938fd1498Szrj   pp_underscore (buffer);
156038fd1498Szrj 
156138fd1498Szrj   if (DECL_NAME (t2))
156238fd1498Szrj     pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, 0, false);
156338fd1498Szrj   else
156438fd1498Szrj     {
156538fd1498Szrj       pp_string (buffer, "anon");
156638fd1498Szrj       pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t2)));
156738fd1498Szrj     }
156838fd1498Szrj 
156938fd1498Szrj   switch (TREE_CODE (TREE_TYPE (t2)))
157038fd1498Szrj     {
157138fd1498Szrj     case ARRAY_TYPE:
157238fd1498Szrj       pp_string (buffer, "_array");
157338fd1498Szrj       break;
157438fd1498Szrj     case ENUMERAL_TYPE:
157538fd1498Szrj       pp_string (buffer, "_enum");
157638fd1498Szrj       break;
157738fd1498Szrj     case RECORD_TYPE:
157838fd1498Szrj       pp_string (buffer, "_struct");
157938fd1498Szrj       break;
158038fd1498Szrj     case UNION_TYPE:
158138fd1498Szrj       pp_string (buffer, "_union");
158238fd1498Szrj       break;
158338fd1498Szrj     default:
158438fd1498Szrj       pp_string (buffer, "_unknown");
158538fd1498Szrj       break;
158638fd1498Szrj     }
158738fd1498Szrj }
158838fd1498Szrj 
158938fd1498Szrj /* Dump in BUFFER pragma Import C/CPP on a given node T.  */
159038fd1498Szrj 
159138fd1498Szrj static void
dump_ada_import(pretty_printer * buffer,tree t)159238fd1498Szrj dump_ada_import (pretty_printer *buffer, tree t)
159338fd1498Szrj {
159438fd1498Szrj   const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
159538fd1498Szrj   const bool is_stdcall
159638fd1498Szrj     = TREE_CODE (t) == FUNCTION_DECL
159738fd1498Szrj       && lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (t)));
159838fd1498Szrj 
159938fd1498Szrj   if (is_stdcall)
160038fd1498Szrj     pp_string (buffer, "pragma Import (Stdcall, ");
160138fd1498Szrj   else if (name[0] == '_' && name[1] == 'Z')
160238fd1498Szrj     pp_string (buffer, "pragma Import (CPP, ");
160338fd1498Szrj   else
160438fd1498Szrj     pp_string (buffer, "pragma Import (C, ");
160538fd1498Szrj 
160638fd1498Szrj   dump_ada_decl_name (buffer, t, false);
160738fd1498Szrj   pp_string (buffer, ", \"");
160838fd1498Szrj 
160938fd1498Szrj   if (is_stdcall)
161038fd1498Szrj     pp_string (buffer, IDENTIFIER_POINTER (DECL_NAME (t)));
161138fd1498Szrj   else
161238fd1498Szrj     pp_asm_name (buffer, t);
161338fd1498Szrj 
161438fd1498Szrj   pp_string (buffer, "\");");
161538fd1498Szrj }
161638fd1498Szrj 
161738fd1498Szrj /* Check whether T and its type have different names, and append "the_"
161838fd1498Szrj    otherwise in BUFFER.  */
161938fd1498Szrj 
162038fd1498Szrj static void
check_name(pretty_printer * buffer,tree t)162138fd1498Szrj check_name (pretty_printer *buffer, tree t)
162238fd1498Szrj {
162338fd1498Szrj   const char *s;
162438fd1498Szrj   tree tmp = TREE_TYPE (t);
162538fd1498Szrj 
162638fd1498Szrj   while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp))
162738fd1498Szrj     tmp = TREE_TYPE (tmp);
162838fd1498Szrj 
162938fd1498Szrj   if (TREE_CODE (tmp) != FUNCTION_TYPE)
163038fd1498Szrj     {
163138fd1498Szrj       if (TREE_CODE (tmp) == IDENTIFIER_NODE)
163238fd1498Szrj 	s = IDENTIFIER_POINTER (tmp);
163338fd1498Szrj       else if (!TYPE_NAME (tmp))
163438fd1498Szrj 	s = "";
163538fd1498Szrj       else if (TREE_CODE (TYPE_NAME (tmp)) == IDENTIFIER_NODE)
163638fd1498Szrj 	s = IDENTIFIER_POINTER (TYPE_NAME (tmp));
163738fd1498Szrj       else
163838fd1498Szrj 	s = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp)));
163938fd1498Szrj 
164038fd1498Szrj       if (!strcasecmp (IDENTIFIER_POINTER (DECL_NAME (t)), s))
164138fd1498Szrj 	pp_string (buffer, "the_");
164238fd1498Szrj     }
164338fd1498Szrj }
164438fd1498Szrj 
164538fd1498Szrj /* Dump in BUFFER a function declaration FUNC in Ada syntax.
164638fd1498Szrj    IS_METHOD indicates whether FUNC is a C++ method.
164738fd1498Szrj    IS_CONSTRUCTOR whether FUNC is a C++ constructor.
164838fd1498Szrj    IS_DESTRUCTOR whether FUNC is a C++ destructor.
164938fd1498Szrj    SPC is the current indentation level.  */
165038fd1498Szrj 
165138fd1498Szrj static void
dump_ada_function_declaration(pretty_printer * buffer,tree func,bool is_method,bool is_constructor,bool is_destructor,int spc)165238fd1498Szrj dump_ada_function_declaration (pretty_printer *buffer, tree func,
165338fd1498Szrj 			       bool is_method, bool is_constructor,
165438fd1498Szrj 			       bool is_destructor, int spc)
165538fd1498Szrj {
165638fd1498Szrj   tree arg;
165738fd1498Szrj   const tree node = TREE_TYPE (func);
165838fd1498Szrj   char buf[17];
165938fd1498Szrj   int num = 0, num_args = 0, have_args = true, have_ellipsis = false;
166038fd1498Szrj 
166138fd1498Szrj   /* Compute number of arguments.  */
166238fd1498Szrj   arg = TYPE_ARG_TYPES (node);
166338fd1498Szrj 
166438fd1498Szrj   if (arg)
166538fd1498Szrj     {
166638fd1498Szrj       while (TREE_CHAIN (arg) && arg != error_mark_node)
166738fd1498Szrj 	{
166838fd1498Szrj 	  num_args++;
166938fd1498Szrj 	  arg = TREE_CHAIN (arg);
167038fd1498Szrj 	}
167138fd1498Szrj 
167238fd1498Szrj       if (TREE_CODE (TREE_VALUE (arg)) != VOID_TYPE)
167338fd1498Szrj 	{
167438fd1498Szrj 	  num_args++;
167538fd1498Szrj 	  have_ellipsis = true;
167638fd1498Szrj 	}
167738fd1498Szrj     }
167838fd1498Szrj 
167938fd1498Szrj   if (is_constructor)
168038fd1498Szrj     num_args--;
168138fd1498Szrj 
168238fd1498Szrj   if (is_destructor)
168338fd1498Szrj     num_args = 1;
168438fd1498Szrj 
168538fd1498Szrj   if (num_args > 2)
168638fd1498Szrj     newline_and_indent (buffer, spc + 1);
168738fd1498Szrj 
168838fd1498Szrj   if (num_args > 0)
168938fd1498Szrj     {
169038fd1498Szrj       pp_space (buffer);
169138fd1498Szrj       pp_left_paren (buffer);
169238fd1498Szrj     }
169338fd1498Szrj 
169438fd1498Szrj   if (TREE_CODE (func) == FUNCTION_DECL)
169538fd1498Szrj     arg = DECL_ARGUMENTS (func);
169638fd1498Szrj   else
169738fd1498Szrj     arg = NULL_TREE;
169838fd1498Szrj 
169938fd1498Szrj   if (arg == NULL_TREE)
170038fd1498Szrj     {
170138fd1498Szrj       have_args = false;
170238fd1498Szrj       arg = TYPE_ARG_TYPES (node);
170338fd1498Szrj 
170438fd1498Szrj       if (arg && TREE_CODE (TREE_VALUE (arg)) == VOID_TYPE)
170538fd1498Szrj 	arg = NULL_TREE;
170638fd1498Szrj     }
170738fd1498Szrj 
170838fd1498Szrj   if (is_constructor)
170938fd1498Szrj     arg = TREE_CHAIN (arg);
171038fd1498Szrj 
171138fd1498Szrj   /* Print the argument names (if available) & types.  */
171238fd1498Szrj 
171338fd1498Szrj   for (num = 1; num <= num_args; num++)
171438fd1498Szrj     {
171538fd1498Szrj       if (have_args)
171638fd1498Szrj 	{
171738fd1498Szrj 	  if (DECL_NAME (arg))
171838fd1498Szrj 	    {
171938fd1498Szrj 	      check_name (buffer, arg);
172038fd1498Szrj 	      pp_ada_tree_identifier (buffer, DECL_NAME (arg), NULL_TREE, 0,
172138fd1498Szrj 				      false);
172238fd1498Szrj 	      pp_string (buffer, " : ");
172338fd1498Szrj 	    }
172438fd1498Szrj 	  else
172538fd1498Szrj 	    {
172638fd1498Szrj 	      sprintf (buf, "arg%d : ", num);
172738fd1498Szrj 	      pp_string (buffer, buf);
172838fd1498Szrj 	    }
172938fd1498Szrj 
173038fd1498Szrj 	  dump_ada_node (buffer, TREE_TYPE (arg), node, spc, false, true);
173138fd1498Szrj 	}
173238fd1498Szrj       else
173338fd1498Szrj 	{
173438fd1498Szrj 	  sprintf (buf, "arg%d : ", num);
173538fd1498Szrj 	  pp_string (buffer, buf);
173638fd1498Szrj 	  dump_ada_node (buffer, TREE_VALUE (arg), node, spc, false, true);
173738fd1498Szrj 	}
173838fd1498Szrj 
173938fd1498Szrj       /* If the type is a pointer to a tagged type, we need to differentiate
174038fd1498Szrj 	 virtual methods from the rest (non-virtual methods, static member
174138fd1498Szrj 	 or regular functions) and import only them as primitive operations,
174238fd1498Szrj 	 because they make up the virtual table which is mirrored on the Ada
174338fd1498Szrj 	 side by the dispatch table.  So we add 'Class to the type of every
174438fd1498Szrj 	 parameter that is not the first one of a method which either has a
174538fd1498Szrj 	 slot in the virtual table or is a constructor.  */
174638fd1498Szrj       if (TREE_TYPE (arg)
174738fd1498Szrj 	  && POINTER_TYPE_P (TREE_TYPE (arg))
174838fd1498Szrj 	  && is_tagged_type (TREE_TYPE (TREE_TYPE (arg)))
174938fd1498Szrj 	  && !(num == 1 && is_method && (DECL_VINDEX (func) || is_constructor)))
175038fd1498Szrj 	pp_string (buffer, "'Class");
175138fd1498Szrj 
175238fd1498Szrj       arg = TREE_CHAIN (arg);
175338fd1498Szrj 
175438fd1498Szrj       if (num < num_args)
175538fd1498Szrj 	{
175638fd1498Szrj 	  pp_semicolon (buffer);
175738fd1498Szrj 
175838fd1498Szrj 	  if (num_args > 2)
175938fd1498Szrj 	    newline_and_indent (buffer, spc + INDENT_INCR);
176038fd1498Szrj 	  else
176138fd1498Szrj 	    pp_space (buffer);
176238fd1498Szrj 	}
176338fd1498Szrj     }
176438fd1498Szrj 
176538fd1498Szrj   if (have_ellipsis)
176638fd1498Szrj     {
176738fd1498Szrj       pp_string (buffer, "  -- , ...");
176838fd1498Szrj       newline_and_indent (buffer, spc + INDENT_INCR);
176938fd1498Szrj     }
177038fd1498Szrj 
177138fd1498Szrj   if (num_args > 0)
177238fd1498Szrj     pp_right_paren (buffer);
177338fd1498Szrj 
177438fd1498Szrj   if (is_constructor || !VOID_TYPE_P (TREE_TYPE (node)))
177538fd1498Szrj     {
177638fd1498Szrj       pp_string (buffer, " return ");
177738fd1498Szrj       tree type = is_constructor ? DECL_CONTEXT (func) : TREE_TYPE (node);
177838fd1498Szrj       dump_ada_node (buffer, type, type, spc, false, true);
177938fd1498Szrj     }
178038fd1498Szrj }
178138fd1498Szrj 
178238fd1498Szrj /* Dump in BUFFER all the domains associated with an array NODE,
178338fd1498Szrj    in Ada syntax.  SPC is the current indentation level.  */
178438fd1498Szrj 
178538fd1498Szrj static void
dump_ada_array_domains(pretty_printer * buffer,tree node,int spc)178638fd1498Szrj dump_ada_array_domains (pretty_printer *buffer, tree node, int spc)
178738fd1498Szrj {
178838fd1498Szrj   int first = 1;
178938fd1498Szrj   pp_left_paren (buffer);
179038fd1498Szrj 
179138fd1498Szrj   for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node))
179238fd1498Szrj     {
179338fd1498Szrj       tree domain = TYPE_DOMAIN (node);
179438fd1498Szrj 
179538fd1498Szrj       if (domain)
179638fd1498Szrj 	{
179738fd1498Szrj 	  tree min = TYPE_MIN_VALUE (domain);
179838fd1498Szrj 	  tree max = TYPE_MAX_VALUE (domain);
179938fd1498Szrj 
180038fd1498Szrj 	  if (!first)
180138fd1498Szrj 	    pp_string (buffer, ", ");
180238fd1498Szrj 	  first = 0;
180338fd1498Szrj 
180438fd1498Szrj 	  if (min)
180538fd1498Szrj 	    dump_ada_node (buffer, min, NULL_TREE, spc, false, true);
180638fd1498Szrj 	  pp_string (buffer, " .. ");
180738fd1498Szrj 
180838fd1498Szrj 	  /* If the upper bound is zero, gcc may generate a NULL_TREE
180938fd1498Szrj 	     for TYPE_MAX_VALUE rather than an integer_cst.  */
181038fd1498Szrj 	  if (max)
181138fd1498Szrj 	    dump_ada_node (buffer, max, NULL_TREE, spc, false, true);
181238fd1498Szrj 	  else
181338fd1498Szrj 	    pp_string (buffer, "0");
181438fd1498Szrj 	}
181538fd1498Szrj       else
181638fd1498Szrj 	pp_string (buffer, "size_t");
181738fd1498Szrj     }
181838fd1498Szrj   pp_right_paren (buffer);
181938fd1498Szrj }
182038fd1498Szrj 
182138fd1498Szrj /* Dump in BUFFER file:line information related to NODE.  */
182238fd1498Szrj 
182338fd1498Szrj static void
dump_sloc(pretty_printer * buffer,tree node)182438fd1498Szrj dump_sloc (pretty_printer *buffer, tree node)
182538fd1498Szrj {
182638fd1498Szrj   expanded_location xloc;
182738fd1498Szrj 
182838fd1498Szrj   xloc.file = NULL;
182938fd1498Szrj 
183038fd1498Szrj   if (DECL_P (node))
183138fd1498Szrj     xloc = expand_location (DECL_SOURCE_LOCATION (node));
183238fd1498Szrj   else if (EXPR_HAS_LOCATION (node))
183338fd1498Szrj     xloc = expand_location (EXPR_LOCATION (node));
183438fd1498Szrj 
183538fd1498Szrj   if (xloc.file)
183638fd1498Szrj     {
183738fd1498Szrj       pp_string (buffer, xloc.file);
183838fd1498Szrj       pp_colon (buffer);
183938fd1498Szrj       pp_decimal_int (buffer, xloc.line);
184038fd1498Szrj     }
184138fd1498Szrj }
184238fd1498Szrj 
184338fd1498Szrj /* Return true if type T designates a 1-dimension array of "char".  */
184438fd1498Szrj 
184538fd1498Szrj static bool
is_char_array(tree t)184638fd1498Szrj is_char_array (tree t)
184738fd1498Szrj {
184838fd1498Szrj   int num_dim = 0;
184938fd1498Szrj 
185038fd1498Szrj   while (TREE_CODE (t) == ARRAY_TYPE)
185138fd1498Szrj     {
185238fd1498Szrj       num_dim++;
185338fd1498Szrj       t = TREE_TYPE (t);
185438fd1498Szrj     }
185538fd1498Szrj 
185638fd1498Szrj   return num_dim == 1
185738fd1498Szrj 	 && TREE_CODE (t) == INTEGER_TYPE
185838fd1498Szrj 	 && id_equal (DECL_NAME (TYPE_NAME (t)), "char");
185938fd1498Szrj }
186038fd1498Szrj 
186138fd1498Szrj /* Dump in BUFFER an array type NODE of type TYPE in Ada syntax.  SPC is the
186238fd1498Szrj    indentation level.  */
186338fd1498Szrj 
186438fd1498Szrj static void
dump_ada_array_type(pretty_printer * buffer,tree node,tree type,int spc)186538fd1498Szrj dump_ada_array_type (pretty_printer *buffer, tree node, tree type, int spc)
186638fd1498Szrj {
186738fd1498Szrj   const bool char_array = is_char_array (node);
186838fd1498Szrj 
186938fd1498Szrj   /* Special case char arrays.  */
187038fd1498Szrj   if (char_array)
187138fd1498Szrj     pp_string (buffer, "Interfaces.C.char_array ");
187238fd1498Szrj   else
187338fd1498Szrj     pp_string (buffer, "array ");
187438fd1498Szrj 
187538fd1498Szrj   /* Print the dimensions.  */
187638fd1498Szrj   dump_ada_array_domains (buffer, node, spc);
187738fd1498Szrj 
187838fd1498Szrj   /* Print array's type.  */
187938fd1498Szrj   if (!char_array)
188038fd1498Szrj     {
188138fd1498Szrj       /* Retrieve the element type.  */
188238fd1498Szrj       tree tmp = node;
188338fd1498Szrj       while (TREE_CODE (tmp) == ARRAY_TYPE)
188438fd1498Szrj 	tmp = TREE_TYPE (tmp);
188538fd1498Szrj 
188638fd1498Szrj       pp_string (buffer, " of ");
188738fd1498Szrj 
188838fd1498Szrj       if (TREE_CODE (tmp) != POINTER_TYPE)
188938fd1498Szrj 	pp_string (buffer, "aliased ");
189038fd1498Szrj 
189138fd1498Szrj       if (TYPE_NAME (tmp) || !RECORD_OR_UNION_TYPE_P (tmp))
189238fd1498Szrj 	dump_ada_node (buffer, tmp, node, spc, false, true);
189338fd1498Szrj       else
189438fd1498Szrj 	dump_ada_double_name (buffer, type, get_underlying_decl (tmp));
189538fd1498Szrj     }
189638fd1498Szrj }
189738fd1498Szrj 
189838fd1498Szrj /* Dump in BUFFER type names associated with a template, each prepended with
189938fd1498Szrj    '_'.  TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.  SPC is
190038fd1498Szrj    the indentation level.  */
190138fd1498Szrj 
190238fd1498Szrj static void
dump_template_types(pretty_printer * buffer,tree types,int spc)190338fd1498Szrj dump_template_types (pretty_printer *buffer, tree types, int spc)
190438fd1498Szrj {
190538fd1498Szrj   for (int i = 0; i < TREE_VEC_LENGTH (types); i++)
190638fd1498Szrj     {
190738fd1498Szrj       tree elem = TREE_VEC_ELT (types, i);
190838fd1498Szrj       pp_underscore (buffer);
190938fd1498Szrj 
191038fd1498Szrj       if (!dump_ada_node (buffer, elem, NULL_TREE, spc, false, true))
191138fd1498Szrj 	{
191238fd1498Szrj 	  pp_string (buffer, "unknown");
191338fd1498Szrj 	  pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
191438fd1498Szrj 	}
191538fd1498Szrj     }
191638fd1498Szrj }
191738fd1498Szrj 
191838fd1498Szrj /* Dump in BUFFER the contents of all class instantiations associated with
191938fd1498Szrj    a given template T.  SPC is the indentation level.  */
192038fd1498Szrj 
192138fd1498Szrj static int
dump_ada_template(pretty_printer * buffer,tree t,int spc)192238fd1498Szrj dump_ada_template (pretty_printer *buffer, tree t, int spc)
192338fd1498Szrj {
192438fd1498Szrj   /* DECL_SIZE_UNIT is DECL_TEMPLATE_INSTANTIATIONS in this context.  */
192538fd1498Szrj   tree inst = DECL_SIZE_UNIT (t);
192638fd1498Szrj   /* This emulates DECL_TEMPLATE_RESULT in this context.  */
192738fd1498Szrj   struct tree_template_decl {
192838fd1498Szrj     struct tree_decl_common common;
192938fd1498Szrj     tree arguments;
193038fd1498Szrj     tree result;
193138fd1498Szrj   };
193238fd1498Szrj   tree result = ((struct tree_template_decl *) t)->result;
193338fd1498Szrj   int num_inst = 0;
193438fd1498Szrj 
193538fd1498Szrj   /* Don't look at template declarations declaring something coming from
193638fd1498Szrj      another file.  This can occur for template friend declarations.  */
193738fd1498Szrj   if (LOCATION_FILE (decl_sloc (result, false))
193838fd1498Szrj       != LOCATION_FILE (decl_sloc (t, false)))
193938fd1498Szrj     return 0;
194038fd1498Szrj 
194138fd1498Szrj   for (; inst && inst != error_mark_node; inst = TREE_CHAIN (inst))
194238fd1498Szrj     {
194338fd1498Szrj       tree types = TREE_PURPOSE (inst);
194438fd1498Szrj       tree instance = TREE_VALUE (inst);
194538fd1498Szrj 
194638fd1498Szrj       if (TREE_VEC_LENGTH (types) == 0)
194738fd1498Szrj 	break;
194838fd1498Szrj 
194938fd1498Szrj       if (!RECORD_OR_UNION_TYPE_P (instance))
195038fd1498Szrj 	break;
195138fd1498Szrj 
195238fd1498Szrj       /* We are interested in concrete template instantiations only: skip
195338fd1498Szrj 	 partially specialized nodes.  */
195438fd1498Szrj       if (RECORD_OR_UNION_TYPE_P (instance)
195538fd1498Szrj 	  && cpp_check
195638fd1498Szrj 	  && cpp_check (instance, HAS_DEPENDENT_TEMPLATE_ARGS))
195738fd1498Szrj 	continue;
195838fd1498Szrj 
195938fd1498Szrj       num_inst++;
196038fd1498Szrj       INDENT (spc);
196138fd1498Szrj       pp_string (buffer, "package ");
196238fd1498Szrj       package_prefix = false;
196338fd1498Szrj       dump_ada_node (buffer, instance, t, spc, false, true);
196438fd1498Szrj       dump_template_types (buffer, types, spc);
196538fd1498Szrj       pp_string (buffer, " is");
196638fd1498Szrj       spc += INDENT_INCR;
196738fd1498Szrj       newline_and_indent (buffer, spc);
196838fd1498Szrj 
196938fd1498Szrj       TREE_VISITED (get_underlying_decl (instance)) = 1;
197038fd1498Szrj       pp_string (buffer, "type ");
197138fd1498Szrj       dump_ada_node (buffer, instance, t, spc, false, true);
197238fd1498Szrj       package_prefix = true;
197338fd1498Szrj 
197438fd1498Szrj       if (is_tagged_type (instance))
197538fd1498Szrj 	pp_string (buffer, " is tagged limited ");
197638fd1498Szrj       else
197738fd1498Szrj 	pp_string (buffer, " is limited ");
197838fd1498Szrj 
197938fd1498Szrj       dump_ada_node (buffer, instance, t, spc, false, false);
198038fd1498Szrj       pp_newline (buffer);
198138fd1498Szrj       spc -= INDENT_INCR;
198238fd1498Szrj       newline_and_indent (buffer, spc);
198338fd1498Szrj 
198438fd1498Szrj       pp_string (buffer, "end;");
198538fd1498Szrj       newline_and_indent (buffer, spc);
198638fd1498Szrj       pp_string (buffer, "use ");
198738fd1498Szrj       package_prefix = false;
198838fd1498Szrj       dump_ada_node (buffer, instance, t, spc, false, true);
198938fd1498Szrj       dump_template_types (buffer, types, spc);
199038fd1498Szrj       package_prefix = true;
199138fd1498Szrj       pp_semicolon (buffer);
199238fd1498Szrj       pp_newline (buffer);
199338fd1498Szrj       pp_newline (buffer);
199438fd1498Szrj     }
199538fd1498Szrj 
199638fd1498Szrj   return num_inst > 0;
199738fd1498Szrj }
199838fd1498Szrj 
199938fd1498Szrj /* Return true if NODE is a simple enum types, that can be mapped to an
200038fd1498Szrj    Ada enum type directly.  */
200138fd1498Szrj 
200238fd1498Szrj static bool
is_simple_enum(tree node)200338fd1498Szrj is_simple_enum (tree node)
200438fd1498Szrj {
200538fd1498Szrj   HOST_WIDE_INT count = 0;
200638fd1498Szrj 
200738fd1498Szrj   for (tree value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
200838fd1498Szrj     {
200938fd1498Szrj       tree int_val = TREE_VALUE (value);
201038fd1498Szrj 
201138fd1498Szrj       if (TREE_CODE (int_val) != INTEGER_CST)
201238fd1498Szrj 	int_val = DECL_INITIAL (int_val);
201338fd1498Szrj 
201438fd1498Szrj       if (!tree_fits_shwi_p (int_val))
201538fd1498Szrj 	return false;
201638fd1498Szrj       else if (tree_to_shwi (int_val) != count)
201738fd1498Szrj 	return false;
201838fd1498Szrj 
201938fd1498Szrj       count++;
202038fd1498Szrj     }
202138fd1498Szrj 
202238fd1498Szrj   return true;
202338fd1498Szrj }
202438fd1498Szrj 
202538fd1498Szrj /* Dump in BUFFER an enumeral type NODE of type TYPE in Ada syntax.  SPC is
202638fd1498Szrj    the indentation level.  If DISPLAY_CONVENTION is true, also print the
202738fd1498Szrj    pragma Convention for NODE.  */
202838fd1498Szrj 
202938fd1498Szrj static void
dump_ada_enum_type(pretty_printer * buffer,tree node,tree type,int spc,bool display_convention)203038fd1498Szrj dump_ada_enum_type (pretty_printer *buffer, tree node, tree type, int spc,
203138fd1498Szrj 		    bool display_convention)
203238fd1498Szrj {
203338fd1498Szrj   if (is_simple_enum (node))
203438fd1498Szrj     {
203538fd1498Szrj       bool first = true;
203638fd1498Szrj       spc += INDENT_INCR;
203738fd1498Szrj       newline_and_indent (buffer, spc - 1);
203838fd1498Szrj       pp_left_paren (buffer);
203938fd1498Szrj       for (tree value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
204038fd1498Szrj 	{
204138fd1498Szrj 	  if (first)
204238fd1498Szrj 	    first = false;
204338fd1498Szrj 	  else
204438fd1498Szrj 	    {
204538fd1498Szrj 	      pp_comma (buffer);
204638fd1498Szrj 	      newline_and_indent (buffer, spc);
204738fd1498Szrj 	    }
204838fd1498Szrj 
204938fd1498Szrj 	  pp_ada_tree_identifier (buffer, TREE_PURPOSE (value), node, 0, false);
205038fd1498Szrj 	}
205138fd1498Szrj       pp_string (buffer, ");");
205238fd1498Szrj       spc -= INDENT_INCR;
205338fd1498Szrj       newline_and_indent (buffer, spc);
205438fd1498Szrj 
205538fd1498Szrj       if (display_convention)
205638fd1498Szrj 	{
205738fd1498Szrj 	  pp_string (buffer, "pragma Convention (C, ");
205838fd1498Szrj 	  dump_ada_node (buffer, DECL_NAME (type) ? type : TYPE_NAME (node),
205938fd1498Szrj 		     type, spc, false, true);
206038fd1498Szrj 	  pp_right_paren (buffer);
206138fd1498Szrj 	}
206238fd1498Szrj     }
206338fd1498Szrj   else
206438fd1498Szrj     {
206538fd1498Szrj       if (TYPE_UNSIGNED (node))
206638fd1498Szrj 	pp_string (buffer, "unsigned");
206738fd1498Szrj       else
206838fd1498Szrj 	pp_string (buffer, "int");
206938fd1498Szrj       for (tree value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
207038fd1498Szrj 	{
207138fd1498Szrj 	  pp_semicolon (buffer);
207238fd1498Szrj 	  newline_and_indent (buffer, spc);
207338fd1498Szrj 
207438fd1498Szrj 	  pp_ada_tree_identifier (buffer, TREE_PURPOSE (value), node, 0, false);
207538fd1498Szrj 	  pp_string (buffer, " : constant ");
207638fd1498Szrj 
207738fd1498Szrj 	  if (TYPE_UNSIGNED (node))
207838fd1498Szrj 	    pp_string (buffer, "unsigned");
207938fd1498Szrj 	  else
208038fd1498Szrj 	    pp_string (buffer, "int");
208138fd1498Szrj 
208238fd1498Szrj 	  pp_string (buffer, " := ");
208338fd1498Szrj 	  dump_ada_node (buffer,
208438fd1498Szrj 			 TREE_CODE (TREE_VALUE (value)) == INTEGER_CST
208538fd1498Szrj 			 ? TREE_VALUE (value)
208638fd1498Szrj 			 : DECL_INITIAL (TREE_VALUE (value)),
208738fd1498Szrj 			 node, spc, false, true);
208838fd1498Szrj 	}
208938fd1498Szrj     }
209038fd1498Szrj }
209138fd1498Szrj 
209238fd1498Szrj static bool bitfield_used = false;
209338fd1498Szrj 
209438fd1498Szrj /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
209538fd1498Szrj    TYPE.  SPC is the indentation level.  LIMITED_ACCESS indicates whether NODE
209638fd1498Szrj    can be referenced via a "limited with" clause.  NAME_ONLY indicates whether
209738fd1498Szrj    we should only dump the name of NODE, instead of its full declaration.  */
209838fd1498Szrj 
209938fd1498Szrj static int
dump_ada_node(pretty_printer * buffer,tree node,tree type,int spc,bool limited_access,bool name_only)210038fd1498Szrj dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
210138fd1498Szrj 	       bool limited_access, bool name_only)
210238fd1498Szrj {
210338fd1498Szrj   if (node == NULL_TREE)
210438fd1498Szrj     return 0;
210538fd1498Szrj 
210638fd1498Szrj   switch (TREE_CODE (node))
210738fd1498Szrj     {
210838fd1498Szrj     case ERROR_MARK:
210938fd1498Szrj       pp_string (buffer, "<<< error >>>");
211038fd1498Szrj       return 0;
211138fd1498Szrj 
211238fd1498Szrj     case IDENTIFIER_NODE:
211338fd1498Szrj       pp_ada_tree_identifier (buffer, node, type, 0, limited_access);
211438fd1498Szrj       break;
211538fd1498Szrj 
211638fd1498Szrj     case TREE_LIST:
211738fd1498Szrj       pp_string (buffer, "--- unexpected node: TREE_LIST");
211838fd1498Szrj       return 0;
211938fd1498Szrj 
212038fd1498Szrj     case TREE_BINFO:
212138fd1498Szrj       dump_ada_node (buffer, BINFO_TYPE (node), type, spc, limited_access,
212238fd1498Szrj 		     name_only);
212338fd1498Szrj       return 0;
212438fd1498Szrj 
212538fd1498Szrj     case TREE_VEC:
212638fd1498Szrj       pp_string (buffer, "--- unexpected node: TREE_VEC");
212738fd1498Szrj       return 0;
212838fd1498Szrj 
212938fd1498Szrj     case NULLPTR_TYPE:
213038fd1498Szrj     case VOID_TYPE:
213138fd1498Szrj       if (package_prefix)
213238fd1498Szrj 	{
213338fd1498Szrj 	  append_withs ("System", false);
213438fd1498Szrj 	  pp_string (buffer, "System.Address");
213538fd1498Szrj 	}
213638fd1498Szrj       else
213738fd1498Szrj 	pp_string (buffer, "address");
213838fd1498Szrj       break;
213938fd1498Szrj 
214038fd1498Szrj     case VECTOR_TYPE:
214138fd1498Szrj       pp_string (buffer, "<vector>");
214238fd1498Szrj       break;
214338fd1498Szrj 
214438fd1498Szrj     case COMPLEX_TYPE:
214538fd1498Szrj       pp_string (buffer, "<complex>");
214638fd1498Szrj       break;
214738fd1498Szrj 
214838fd1498Szrj     case ENUMERAL_TYPE:
214938fd1498Szrj       if (name_only)
215038fd1498Szrj 	dump_ada_node (buffer, TYPE_NAME (node), node, spc, false, true);
215138fd1498Szrj       else
215238fd1498Szrj 	dump_ada_enum_type (buffer, node, type, spc, true);
215338fd1498Szrj       break;
215438fd1498Szrj 
215538fd1498Szrj     case REAL_TYPE:
215638fd1498Szrj       if (TYPE_NAME (node)
215738fd1498Szrj 	  && TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
215838fd1498Szrj 	  && IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))) [0] == '_'
215938fd1498Szrj 	  && (id_equal (DECL_NAME (TYPE_NAME (node)), "_Float128")
216038fd1498Szrj 	      || id_equal (DECL_NAME (TYPE_NAME (node)), "__float128")))
216138fd1498Szrj 	{
216238fd1498Szrj 	  append_withs ("Interfaces.C.Extensions", false);
216338fd1498Szrj 	  pp_string (buffer, "Extensions.Float_128");
216438fd1498Szrj 	  break;
216538fd1498Szrj 	}
216638fd1498Szrj       /* fallthrough */
216738fd1498Szrj 
216838fd1498Szrj     case INTEGER_TYPE:
216938fd1498Szrj     case FIXED_POINT_TYPE:
217038fd1498Szrj     case BOOLEAN_TYPE:
217138fd1498Szrj       if (TYPE_NAME (node))
217238fd1498Szrj 	{
217338fd1498Szrj 	  if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
217438fd1498Szrj 	    pp_ada_tree_identifier (buffer, TYPE_NAME (node), node, 0,
217538fd1498Szrj 				    limited_access);
217638fd1498Szrj 	  else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
217738fd1498Szrj 		   && DECL_NAME (TYPE_NAME (node)))
217838fd1498Szrj 	    dump_ada_decl_name (buffer, TYPE_NAME (node), limited_access);
217938fd1498Szrj 	  else
218038fd1498Szrj 	    pp_string (buffer, "<unnamed type>");
218138fd1498Szrj 	}
218238fd1498Szrj       else if (TREE_CODE (node) == INTEGER_TYPE)
218338fd1498Szrj 	{
218438fd1498Szrj 	  append_withs ("Interfaces.C.Extensions", false);
218538fd1498Szrj 	  bitfield_used = true;
218638fd1498Szrj 
218738fd1498Szrj 	  if (TYPE_PRECISION (node) == 1)
218838fd1498Szrj 	    pp_string (buffer, "Extensions.Unsigned_1");
218938fd1498Szrj 	  else
219038fd1498Szrj 	    {
219138fd1498Szrj 	      pp_string (buffer, TYPE_UNSIGNED (node)
219238fd1498Szrj 				 ? "Extensions.Unsigned_"
219338fd1498Szrj 				 : "Extensions.Signed_");
219438fd1498Szrj 	      pp_decimal_int (buffer, TYPE_PRECISION (node));
219538fd1498Szrj 	    }
219638fd1498Szrj 	}
219738fd1498Szrj       else
219838fd1498Szrj 	pp_string (buffer, "<unnamed type>");
219938fd1498Szrj       break;
220038fd1498Szrj 
220138fd1498Szrj     case POINTER_TYPE:
220238fd1498Szrj     case REFERENCE_TYPE:
220338fd1498Szrj       if (name_only && TYPE_NAME (node))
220438fd1498Szrj 	dump_ada_node (buffer, TYPE_NAME (node), node, spc, limited_access,
220538fd1498Szrj 		       true);
220638fd1498Szrj 
220738fd1498Szrj       else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
220838fd1498Szrj 	{
220938fd1498Szrj 	  if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (node))))
221038fd1498Szrj 	    pp_string (buffer, "access procedure");
221138fd1498Szrj 	  else
221238fd1498Szrj 	    pp_string (buffer, "access function");
221338fd1498Szrj 
221438fd1498Szrj 	  dump_ada_function_declaration (buffer, node, false, false, false,
221538fd1498Szrj 					 spc + INDENT_INCR);
221638fd1498Szrj 
221738fd1498Szrj 	  /* If we are dumping the full type, it means we are part of a
221838fd1498Szrj 	     type definition and need also a Convention C pragma.  */
221938fd1498Szrj 	  if (!name_only)
222038fd1498Szrj 	    {
222138fd1498Szrj 	      pp_semicolon (buffer);
222238fd1498Szrj 	      newline_and_indent (buffer, spc);
222338fd1498Szrj 	      pp_string (buffer, "pragma Convention (C, ");
222438fd1498Szrj 	      dump_ada_node (buffer, type, NULL_TREE, spc, false, true);
222538fd1498Szrj 	      pp_right_paren (buffer);
222638fd1498Szrj 	    }
222738fd1498Szrj 	}
222838fd1498Szrj       else
222938fd1498Szrj 	{
223038fd1498Szrj 	  bool is_access = false;
223138fd1498Szrj 	  unsigned int quals = TYPE_QUALS (TREE_TYPE (node));
223238fd1498Szrj 
223338fd1498Szrj 	  if (VOID_TYPE_P (TREE_TYPE (node)))
223438fd1498Szrj 	    {
223538fd1498Szrj 	      if (!name_only)
223638fd1498Szrj 		pp_string (buffer, "new ");
223738fd1498Szrj 	      if (package_prefix)
223838fd1498Szrj 		{
223938fd1498Szrj 		  append_withs ("System", false);
224038fd1498Szrj 		  pp_string (buffer, "System.Address");
224138fd1498Szrj 		}
224238fd1498Szrj 	      else
224338fd1498Szrj 		pp_string (buffer, "address");
224438fd1498Szrj 	    }
224538fd1498Szrj 	  else
224638fd1498Szrj 	    {
224738fd1498Szrj 	      if (TREE_CODE (node) == POINTER_TYPE
224838fd1498Szrj 		  && TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE
224938fd1498Szrj 		  && id_equal (DECL_NAME (TYPE_NAME (TREE_TYPE (node))),
225038fd1498Szrj 			       "char"))
225138fd1498Szrj 		{
225238fd1498Szrj 		  if (!name_only)
225338fd1498Szrj 		    pp_string (buffer, "new ");
225438fd1498Szrj 
225538fd1498Szrj 		  if (package_prefix)
225638fd1498Szrj 		    {
225738fd1498Szrj 		      pp_string (buffer, "Interfaces.C.Strings.chars_ptr");
225838fd1498Szrj 		      append_withs ("Interfaces.C.Strings", false);
225938fd1498Szrj 		    }
226038fd1498Szrj 		  else
226138fd1498Szrj 		    pp_string (buffer, "chars_ptr");
226238fd1498Szrj 		}
226338fd1498Szrj 	      else
226438fd1498Szrj 		{
226538fd1498Szrj 		  tree type_name = TYPE_NAME (TREE_TYPE (node));
226638fd1498Szrj 
226738fd1498Szrj 		  /* For now, handle access-to-access as System.Address.  */
226838fd1498Szrj 		  if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE)
226938fd1498Szrj 		    {
227038fd1498Szrj 		      if (package_prefix)
227138fd1498Szrj 			{
227238fd1498Szrj 			  append_withs ("System", false);
227338fd1498Szrj 			  if (!name_only)
227438fd1498Szrj 			    pp_string (buffer, "new ");
227538fd1498Szrj 			  pp_string (buffer, "System.Address");
227638fd1498Szrj 			}
227738fd1498Szrj 		      else
227838fd1498Szrj 			pp_string (buffer, "address");
227938fd1498Szrj 		      return spc;
228038fd1498Szrj 		    }
228138fd1498Szrj 
228238fd1498Szrj 		  if (!package_prefix)
228338fd1498Szrj 		    pp_string (buffer, "access");
228438fd1498Szrj 		  else if (AGGREGATE_TYPE_P (TREE_TYPE (node)))
228538fd1498Szrj 		    {
228638fd1498Szrj 		      if (!type || TREE_CODE (type) != FUNCTION_DECL)
228738fd1498Szrj 			{
228838fd1498Szrj 			  pp_string (buffer, "access ");
228938fd1498Szrj 			  is_access = true;
229038fd1498Szrj 
229138fd1498Szrj 			  if (quals & TYPE_QUAL_CONST)
229238fd1498Szrj 			    pp_string (buffer, "constant ");
229338fd1498Szrj 			  else if (!name_only)
229438fd1498Szrj 			    pp_string (buffer, "all ");
229538fd1498Szrj 			}
229638fd1498Szrj 		      else if (quals & TYPE_QUAL_CONST)
229738fd1498Szrj 			pp_string (buffer, "in ");
229838fd1498Szrj 		      else
229938fd1498Szrj 			{
230038fd1498Szrj 			  is_access = true;
230138fd1498Szrj 			  pp_string (buffer, "access ");
230238fd1498Szrj 			  /* ??? should be configurable: access or in out.  */
230338fd1498Szrj 			}
230438fd1498Szrj 		    }
230538fd1498Szrj 		  else
230638fd1498Szrj 		    {
230738fd1498Szrj 		      is_access = true;
230838fd1498Szrj 		      pp_string (buffer, "access ");
230938fd1498Szrj 
231038fd1498Szrj 		      if (!name_only)
231138fd1498Szrj 			pp_string (buffer, "all ");
231238fd1498Szrj 		    }
231338fd1498Szrj 
231438fd1498Szrj 		  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node)) && type_name)
231538fd1498Szrj 		    dump_ada_node (buffer, type_name, TREE_TYPE (node), spc,
231638fd1498Szrj 				   is_access, true);
231738fd1498Szrj 		  else
231838fd1498Szrj 		    dump_ada_node (buffer, TREE_TYPE (node), TREE_TYPE (node),
231938fd1498Szrj 				   spc, false, true);
232038fd1498Szrj 		}
232138fd1498Szrj 	    }
232238fd1498Szrj 	}
232338fd1498Szrj       break;
232438fd1498Szrj 
232538fd1498Szrj     case ARRAY_TYPE:
232638fd1498Szrj       if (name_only)
232738fd1498Szrj 	dump_ada_node (buffer, TYPE_NAME (node), node, spc, limited_access,
232838fd1498Szrj 		       true);
232938fd1498Szrj       else
233038fd1498Szrj 	dump_ada_array_type (buffer, node, type, spc);
233138fd1498Szrj       break;
233238fd1498Szrj 
233338fd1498Szrj     case RECORD_TYPE:
233438fd1498Szrj     case UNION_TYPE:
233538fd1498Szrj       if (name_only)
233638fd1498Szrj 	dump_ada_node (buffer, TYPE_NAME (node), node, spc, limited_access,
233738fd1498Szrj 		       true);
233838fd1498Szrj       else
233938fd1498Szrj 	dump_ada_structure (buffer, node, type, spc, true);
234038fd1498Szrj       break;
234138fd1498Szrj 
234238fd1498Szrj     case INTEGER_CST:
234338fd1498Szrj       /* We treat the upper half of the sizetype range as negative.  This
234438fd1498Szrj 	 is consistent with the internal treatment and makes it possible
234538fd1498Szrj 	 to generate the (0 .. -1) range for flexible array members.  */
234638fd1498Szrj       if (TREE_TYPE (node) == sizetype)
234738fd1498Szrj 	node = fold_convert (ssizetype, node);
234838fd1498Szrj       if (tree_fits_shwi_p (node))
234938fd1498Szrj 	pp_wide_integer (buffer, tree_to_shwi (node));
235038fd1498Szrj       else if (tree_fits_uhwi_p (node))
235138fd1498Szrj 	pp_unsigned_wide_integer (buffer, tree_to_uhwi (node));
235238fd1498Szrj       else
235338fd1498Szrj 	{
235438fd1498Szrj 	  wide_int val = wi::to_wide (node);
235538fd1498Szrj 	  int i;
235638fd1498Szrj 	  if (wi::neg_p (val))
235738fd1498Szrj 	    {
235838fd1498Szrj 	      pp_minus (buffer);
235938fd1498Szrj 	      val = -val;
236038fd1498Szrj 	    }
236138fd1498Szrj 	  sprintf (pp_buffer (buffer)->digit_buffer,
236238fd1498Szrj 		   "16#%" HOST_WIDE_INT_PRINT "x",
236338fd1498Szrj 		   val.elt (val.get_len () - 1));
236438fd1498Szrj 	  for (i = val.get_len () - 2; i >= 0; i--)
236538fd1498Szrj 	    sprintf (pp_buffer (buffer)->digit_buffer,
236638fd1498Szrj 		     HOST_WIDE_INT_PRINT_PADDED_HEX, val.elt (i));
236738fd1498Szrj 	  pp_string (buffer, pp_buffer (buffer)->digit_buffer);
236838fd1498Szrj 	}
236938fd1498Szrj       break;
237038fd1498Szrj 
237138fd1498Szrj     case REAL_CST:
237238fd1498Szrj     case FIXED_CST:
237338fd1498Szrj     case COMPLEX_CST:
237438fd1498Szrj     case STRING_CST:
237538fd1498Szrj     case VECTOR_CST:
237638fd1498Szrj       return 0;
237738fd1498Szrj 
237838fd1498Szrj     case TYPE_DECL:
237938fd1498Szrj       if (DECL_IS_BUILTIN (node))
238038fd1498Szrj 	{
238138fd1498Szrj 	  /* Don't print the declaration of built-in types.  */
238238fd1498Szrj 	  if (name_only)
238338fd1498Szrj 	    {
238438fd1498Szrj 	      /* If we're in the middle of a declaration, defaults to
238538fd1498Szrj 		 System.Address.  */
238638fd1498Szrj 	      if (package_prefix)
238738fd1498Szrj 		{
238838fd1498Szrj 		  append_withs ("System", false);
238938fd1498Szrj 		  pp_string (buffer, "System.Address");
239038fd1498Szrj 		}
239138fd1498Szrj 	      else
239238fd1498Szrj 		pp_string (buffer, "address");
239338fd1498Szrj 	    }
239438fd1498Szrj 	  break;
239538fd1498Szrj 	}
239638fd1498Szrj 
239738fd1498Szrj       if (name_only)
239838fd1498Szrj 	dump_ada_decl_name (buffer, node, limited_access);
239938fd1498Szrj       else
240038fd1498Szrj 	{
240138fd1498Szrj 	  if (is_tagged_type (TREE_TYPE (node)))
240238fd1498Szrj 	    {
240338fd1498Szrj 	      int first = true;
240438fd1498Szrj 
240538fd1498Szrj 	      /* Look for ancestors.  */
240638fd1498Szrj 	      for (tree fld = TYPE_FIELDS (TREE_TYPE (node));
240738fd1498Szrj 		   fld;
240838fd1498Szrj 		   fld = TREE_CHAIN (fld))
240938fd1498Szrj 		{
241038fd1498Szrj 		  if (!DECL_NAME (fld) && is_tagged_type (TREE_TYPE (fld)))
241138fd1498Szrj 		    {
241238fd1498Szrj 		      if (first)
241338fd1498Szrj 			{
241438fd1498Szrj 			  pp_string (buffer, "limited new ");
241538fd1498Szrj 			  first = false;
241638fd1498Szrj 			}
241738fd1498Szrj 		      else
241838fd1498Szrj 			pp_string (buffer, " and ");
241938fd1498Szrj 
242038fd1498Szrj 		      dump_ada_decl_name (buffer, TYPE_NAME (TREE_TYPE (fld)),
242138fd1498Szrj 					  false);
242238fd1498Szrj 		    }
242338fd1498Szrj 		}
242438fd1498Szrj 
242538fd1498Szrj 	      pp_string (buffer, first ? "tagged limited " : " with ");
242638fd1498Szrj 	    }
242738fd1498Szrj 	  else if (has_nontrivial_methods (TREE_TYPE (node)))
242838fd1498Szrj 	    pp_string (buffer, "limited ");
242938fd1498Szrj 
243038fd1498Szrj 	  dump_ada_node (buffer, TREE_TYPE (node), type, spc, false, false);
243138fd1498Szrj 	}
243238fd1498Szrj       break;
243338fd1498Szrj 
243438fd1498Szrj     case FUNCTION_DECL:
243538fd1498Szrj     case CONST_DECL:
243638fd1498Szrj     case VAR_DECL:
243738fd1498Szrj     case PARM_DECL:
243838fd1498Szrj     case FIELD_DECL:
243938fd1498Szrj     case NAMESPACE_DECL:
244038fd1498Szrj       dump_ada_decl_name (buffer, node, false);
244138fd1498Szrj       break;
244238fd1498Szrj 
244338fd1498Szrj     default:
244438fd1498Szrj       /* Ignore other nodes (e.g. expressions).  */
244538fd1498Szrj       return 0;
244638fd1498Szrj     }
244738fd1498Szrj 
244838fd1498Szrj   return 1;
244938fd1498Szrj }
245038fd1498Szrj 
245138fd1498Szrj /* Dump in BUFFER NODE's methods.  SPC is the indentation level.  Return 1 if
245238fd1498Szrj    methods were printed, 0 otherwise.  */
245338fd1498Szrj 
245438fd1498Szrj static int
dump_ada_methods(pretty_printer * buffer,tree node,int spc)245538fd1498Szrj dump_ada_methods (pretty_printer *buffer, tree node, int spc)
245638fd1498Szrj {
245738fd1498Szrj   if (!has_nontrivial_methods (node))
245838fd1498Szrj     return 0;
245938fd1498Szrj 
246038fd1498Szrj   pp_semicolon (buffer);
246138fd1498Szrj 
246238fd1498Szrj   int res = 1;
246338fd1498Szrj   for (tree fld = TYPE_FIELDS (node); fld; fld = DECL_CHAIN (fld))
246438fd1498Szrj     if (TREE_CODE (fld) == FUNCTION_DECL)
246538fd1498Szrj       {
246638fd1498Szrj 	if (res)
246738fd1498Szrj 	  {
246838fd1498Szrj 	    pp_newline (buffer);
246938fd1498Szrj 	    pp_newline (buffer);
247038fd1498Szrj 	  }
247138fd1498Szrj 
247238fd1498Szrj 	res = dump_ada_declaration (buffer, fld, node, spc);
247338fd1498Szrj       }
247438fd1498Szrj 
247538fd1498Szrj   return 1;
247638fd1498Szrj }
247738fd1498Szrj 
247838fd1498Szrj /* Dump in BUFFER a forward declaration for TYPE present inside T.
247938fd1498Szrj    SPC is the indentation level.  */
248038fd1498Szrj 
248138fd1498Szrj static void
dump_forward_type(pretty_printer * buffer,tree type,tree t,int spc)248238fd1498Szrj dump_forward_type (pretty_printer *buffer, tree type, tree t, int spc)
248338fd1498Szrj {
248438fd1498Szrj   tree decl = get_underlying_decl (type);
248538fd1498Szrj 
248638fd1498Szrj   /* Anonymous pointer and function types.  */
248738fd1498Szrj   if (!decl)
248838fd1498Szrj     {
248938fd1498Szrj       if (TREE_CODE (type) == POINTER_TYPE)
249038fd1498Szrj 	dump_forward_type (buffer, TREE_TYPE (type), t, spc);
249138fd1498Szrj       else if (TREE_CODE (type) == FUNCTION_TYPE)
249238fd1498Szrj 	{
249338fd1498Szrj 	  function_args_iterator args_iter;
249438fd1498Szrj 	  tree arg;
249538fd1498Szrj 	  dump_forward_type (buffer, TREE_TYPE (type), t, spc);
249638fd1498Szrj 	  FOREACH_FUNCTION_ARGS (type, arg, args_iter)
249738fd1498Szrj 	    dump_forward_type (buffer, arg, t, spc);
249838fd1498Szrj 	}
249938fd1498Szrj       return;
250038fd1498Szrj     }
250138fd1498Szrj 
250238fd1498Szrj   if (DECL_IS_BUILTIN (decl) || TREE_VISITED (decl))
250338fd1498Szrj     return;
250438fd1498Szrj 
250538fd1498Szrj   /* Forward declarations are only needed within a given file.  */
250638fd1498Szrj   if (DECL_SOURCE_FILE (decl) != DECL_SOURCE_FILE (t))
250738fd1498Szrj     return;
250838fd1498Szrj 
250938fd1498Szrj   /* Generate an incomplete type declaration.  */
251038fd1498Szrj   pp_string (buffer, "type ");
251138fd1498Szrj   dump_ada_node (buffer, decl, NULL_TREE, spc, false, true);
251238fd1498Szrj   pp_semicolon (buffer);
251338fd1498Szrj   newline_and_indent (buffer, spc);
251438fd1498Szrj 
251538fd1498Szrj   /* Only one incomplete declaration is legal for a given type.  */
251638fd1498Szrj   TREE_VISITED (decl) = 1;
251738fd1498Szrj }
251838fd1498Szrj 
251938fd1498Szrj static void dump_nested_type (pretty_printer *, tree, tree, tree, int);
252038fd1498Szrj 
252138fd1498Szrj /* Dump in BUFFER anonymous types nested inside T's definition.
252238fd1498Szrj    PARENT is the parent node of T.  SPC is the indentation level.
252338fd1498Szrj 
252438fd1498Szrj    In C anonymous nested tagged types have no name whereas in C++ they have
252538fd1498Szrj    one.  In C their TYPE_DECL is at top level whereas in C++ it is nested.
252638fd1498Szrj    In both languages untagged types (pointers and arrays) have no name.
252738fd1498Szrj    In C++ the nested TYPE_DECLs can come after their associated FIELD_DECL.
252838fd1498Szrj 
252938fd1498Szrj    Therefore, in order to have a common processing for both languages, we
253038fd1498Szrj    disregard anonymous TYPE_DECLs at top level and here we make a first
253138fd1498Szrj    pass on the nested TYPE_DECLs and a second pass on the unnamed types.  */
253238fd1498Szrj 
253338fd1498Szrj static void
dump_nested_types(pretty_printer * buffer,tree t,tree parent,int spc)253438fd1498Szrj dump_nested_types (pretty_printer *buffer, tree t, tree parent, int spc)
253538fd1498Szrj {
253638fd1498Szrj   tree type, field;
253738fd1498Szrj 
253838fd1498Szrj   /* Find possible anonymous pointers/arrays/structs/unions recursively.  */
253938fd1498Szrj   type = TREE_TYPE (t);
254038fd1498Szrj   if (type == NULL_TREE)
254138fd1498Szrj     return;
254238fd1498Szrj 
254338fd1498Szrj   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
254438fd1498Szrj     if (TREE_CODE (field) == TYPE_DECL
254538fd1498Szrj 	&& DECL_NAME (field) != DECL_NAME (t)
254638fd1498Szrj 	&& !DECL_ORIGINAL_TYPE (field)
254738fd1498Szrj 	&& TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (type))
254838fd1498Szrj       dump_nested_type (buffer, field, t, parent, spc);
254938fd1498Szrj 
255038fd1498Szrj   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
255138fd1498Szrj     if (TREE_CODE (field) == FIELD_DECL && !TYPE_NAME (TREE_TYPE (field)))
255238fd1498Szrj       dump_nested_type (buffer, field, t, parent, spc);
255338fd1498Szrj }
255438fd1498Szrj 
255538fd1498Szrj /* Dump in BUFFER the anonymous type of FIELD inside T.
255638fd1498Szrj    PARENT is the parent node of T.  SPC is the indentation level.  */
255738fd1498Szrj 
255838fd1498Szrj static void
dump_nested_type(pretty_printer * buffer,tree field,tree t,tree parent,int spc)255938fd1498Szrj dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
256038fd1498Szrj 		  int spc)
256138fd1498Szrj {
256238fd1498Szrj   tree field_type = TREE_TYPE (field);
256338fd1498Szrj   tree decl, tmp;
256438fd1498Szrj 
256538fd1498Szrj   switch (TREE_CODE (field_type))
256638fd1498Szrj     {
256738fd1498Szrj     case POINTER_TYPE:
256838fd1498Szrj       tmp = TREE_TYPE (field_type);
256938fd1498Szrj       dump_forward_type (buffer, tmp, t, spc);
257038fd1498Szrj       break;
257138fd1498Szrj 
257238fd1498Szrj     case ARRAY_TYPE:
257338fd1498Szrj       tmp = TREE_TYPE (field_type);
257438fd1498Szrj       while (TREE_CODE (tmp) == ARRAY_TYPE)
257538fd1498Szrj 	tmp = TREE_TYPE (tmp);
257638fd1498Szrj       decl = get_underlying_decl (tmp);
257738fd1498Szrj       if (decl && !DECL_NAME (decl) && !TREE_VISITED (decl))
257838fd1498Szrj 	{
257938fd1498Szrj 	  /* Generate full declaration.  */
258038fd1498Szrj 	  dump_nested_type (buffer, decl, t, parent, spc);
258138fd1498Szrj 	  TREE_VISITED (decl) = 1;
258238fd1498Szrj 	}
258338fd1498Szrj       else if (!decl && TREE_CODE (tmp) == POINTER_TYPE)
258438fd1498Szrj 	dump_forward_type (buffer, TREE_TYPE (tmp), t, spc);
258538fd1498Szrj 
258638fd1498Szrj       /* Special case char arrays.  */
258738fd1498Szrj       if (is_char_array (field_type))
258838fd1498Szrj 	pp_string (buffer, "subtype ");
258938fd1498Szrj       else
259038fd1498Szrj 	pp_string (buffer, "type ");
259138fd1498Szrj 
259238fd1498Szrj       dump_ada_double_name (buffer, parent, field);
259338fd1498Szrj       pp_string (buffer, " is ");
259438fd1498Szrj       dump_ada_array_type (buffer, field_type, parent, spc);
259538fd1498Szrj       pp_semicolon (buffer);
259638fd1498Szrj       newline_and_indent (buffer, spc);
259738fd1498Szrj       break;
259838fd1498Szrj 
259938fd1498Szrj     case ENUMERAL_TYPE:
260038fd1498Szrj       if (is_simple_enum (field_type))
260138fd1498Szrj 	pp_string (buffer, "type ");
260238fd1498Szrj       else
260338fd1498Szrj 	pp_string (buffer, "subtype ");
260438fd1498Szrj 
260538fd1498Szrj       if (TYPE_NAME (field_type))
260638fd1498Szrj 	dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
260738fd1498Szrj       else
260838fd1498Szrj 	dump_ada_double_name (buffer, parent, field);
260938fd1498Szrj       pp_string (buffer, " is ");
261038fd1498Szrj       dump_ada_enum_type (buffer, field_type, t, spc, false);
261138fd1498Szrj 
261238fd1498Szrj       if (is_simple_enum (field_type))
261338fd1498Szrj 	{
261438fd1498Szrj 	  pp_string (buffer, "pragma Convention (C, ");
261538fd1498Szrj 	  if (TYPE_NAME (field_type))
261638fd1498Szrj 	    dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
261738fd1498Szrj 	  else
261838fd1498Szrj 	    dump_ada_double_name (buffer, parent, field);
261938fd1498Szrj 	  pp_string (buffer, ");");
262038fd1498Szrj 	  newline_and_indent (buffer, spc);
262138fd1498Szrj 	}
262238fd1498Szrj       else
262338fd1498Szrj 	{
262438fd1498Szrj 	  pp_semicolon (buffer);
262538fd1498Szrj 	  newline_and_indent (buffer, spc);
262638fd1498Szrj 	}
262738fd1498Szrj       break;
262838fd1498Szrj 
262938fd1498Szrj     case RECORD_TYPE:
263038fd1498Szrj     case UNION_TYPE:
263138fd1498Szrj       dump_nested_types (buffer, field, t, spc);
263238fd1498Szrj 
263338fd1498Szrj       pp_string (buffer, "type ");
263438fd1498Szrj 
263538fd1498Szrj       if (TYPE_NAME (field_type))
263638fd1498Szrj 	dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
263738fd1498Szrj       else
263838fd1498Szrj 	dump_ada_double_name (buffer, parent, field);
263938fd1498Szrj 
264038fd1498Szrj       if (TREE_CODE (field_type) == UNION_TYPE)
264138fd1498Szrj 	pp_string (buffer, " (discr : unsigned := 0)");
264238fd1498Szrj 
264338fd1498Szrj       pp_string (buffer, " is ");
264438fd1498Szrj       dump_ada_structure (buffer, field_type, t, spc, false);
264538fd1498Szrj 
264638fd1498Szrj       pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
264738fd1498Szrj       if (TYPE_NAME (field_type))
264838fd1498Szrj 	dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
264938fd1498Szrj       else
265038fd1498Szrj 	dump_ada_double_name (buffer, parent, field);
265138fd1498Szrj       pp_string (buffer, ");");
265238fd1498Szrj       newline_and_indent (buffer, spc);
265338fd1498Szrj 
265438fd1498Szrj       if (TREE_CODE (field_type) == UNION_TYPE)
265538fd1498Szrj 	{
265638fd1498Szrj 	  pp_string (buffer, "pragma Unchecked_Union (");
265738fd1498Szrj 	  if (TYPE_NAME (field_type))
265838fd1498Szrj 	    dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
265938fd1498Szrj 	  else
266038fd1498Szrj 	    dump_ada_double_name (buffer, parent, field);
266138fd1498Szrj 	  pp_string (buffer, ");");
266238fd1498Szrj 	}
266338fd1498Szrj       break;
266438fd1498Szrj 
266538fd1498Szrj     default:
266638fd1498Szrj       break;
266738fd1498Szrj     }
266838fd1498Szrj }
266938fd1498Szrj 
267038fd1498Szrj /* Dump in BUFFER constructor spec corresponding to T for TYPE.  */
267138fd1498Szrj 
267238fd1498Szrj static void
print_constructor(pretty_printer * buffer,tree t,tree type)267338fd1498Szrj print_constructor (pretty_printer *buffer, tree t, tree type)
267438fd1498Szrj {
267538fd1498Szrj   tree decl_name = DECL_NAME (TYPE_NAME (type));
267638fd1498Szrj 
267738fd1498Szrj   pp_string (buffer, "New_");
267838fd1498Szrj   pp_ada_tree_identifier (buffer, decl_name, t, 0, false);
267938fd1498Szrj }
268038fd1498Szrj 
268138fd1498Szrj /* Dump in BUFFER destructor spec corresponding to T.  */
268238fd1498Szrj 
268338fd1498Szrj static void
print_destructor(pretty_printer * buffer,tree t,tree type)268438fd1498Szrj print_destructor (pretty_printer *buffer, tree t, tree type)
268538fd1498Szrj {
268638fd1498Szrj   tree decl_name = DECL_NAME (TYPE_NAME (type));
268738fd1498Szrj 
268838fd1498Szrj   pp_string (buffer, "Delete_");
2689*e215fc28Szrj   if (strncmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del", 8) == 0)
2690*e215fc28Szrj     pp_string (buffer, "And_Free_");
269138fd1498Szrj   pp_ada_tree_identifier (buffer, decl_name, t, 0, false);
269238fd1498Szrj }
269338fd1498Szrj 
269438fd1498Szrj /* Return the name of type T.  */
269538fd1498Szrj 
269638fd1498Szrj static const char *
type_name(tree t)269738fd1498Szrj type_name (tree t)
269838fd1498Szrj {
269938fd1498Szrj   tree n = TYPE_NAME (t);
270038fd1498Szrj 
270138fd1498Szrj   if (TREE_CODE (n) == IDENTIFIER_NODE)
270238fd1498Szrj     return IDENTIFIER_POINTER (n);
270338fd1498Szrj   else
270438fd1498Szrj     return IDENTIFIER_POINTER (DECL_NAME (n));
270538fd1498Szrj }
270638fd1498Szrj 
270738fd1498Szrj /* Dump in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
270838fd1498Szrj    SPC is the indentation level.  Return 1 if a declaration was printed,
270938fd1498Szrj    0 otherwise.  */
271038fd1498Szrj 
271138fd1498Szrj static int
dump_ada_declaration(pretty_printer * buffer,tree t,tree type,int spc)271238fd1498Szrj dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
271338fd1498Szrj {
271438fd1498Szrj   bool is_var = false;
271538fd1498Szrj   bool need_indent = false;
271638fd1498Szrj   bool is_class = false;
271738fd1498Szrj   tree name = TYPE_NAME (TREE_TYPE (t));
271838fd1498Szrj   tree decl_name = DECL_NAME (t);
271938fd1498Szrj   tree orig = NULL_TREE;
272038fd1498Szrj 
272138fd1498Szrj   if (cpp_check && cpp_check (t, IS_TEMPLATE))
272238fd1498Szrj     return dump_ada_template (buffer, t, spc);
272338fd1498Szrj 
272438fd1498Szrj   /* Skip enumeral values: will be handled as part of the type itself.  */
272538fd1498Szrj   if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
272638fd1498Szrj     return 0;
272738fd1498Szrj 
272838fd1498Szrj   if (TREE_CODE (t) == TYPE_DECL)
272938fd1498Szrj     {
273038fd1498Szrj       orig = DECL_ORIGINAL_TYPE (t);
273138fd1498Szrj 
273238fd1498Szrj       if (orig && TYPE_STUB_DECL (orig))
273338fd1498Szrj 	{
273438fd1498Szrj 	  tree stub = TYPE_STUB_DECL (orig);
273538fd1498Szrj 	  tree typ = TREE_TYPE (stub);
273638fd1498Szrj 
273738fd1498Szrj 	  if (TYPE_NAME (typ))
273838fd1498Szrj 	    {
273958e805e6Szrj 	      /* If the types have the same name (ignoring casing), then ignore
274058e805e6Szrj 		 the second type, but forward declare the first if need be.  */
274138fd1498Szrj 	      if (type_name (typ) == type_name (TREE_TYPE (t))
274238fd1498Szrj 		  || !strcasecmp (type_name (typ), type_name (TREE_TYPE (t))))
274338fd1498Szrj 		{
274458e805e6Szrj 		  if (RECORD_OR_UNION_TYPE_P (typ) && !TREE_VISITED (stub))
274558e805e6Szrj 		    {
274658e805e6Szrj 		      INDENT (spc);
274758e805e6Szrj 		      dump_forward_type (buffer, typ, t, 0);
274858e805e6Szrj 		    }
274958e805e6Szrj 
275038fd1498Szrj 		  TREE_VISITED (t) = 1;
275138fd1498Szrj 		  return 0;
275238fd1498Szrj 		}
275338fd1498Szrj 
275438fd1498Szrj 	      INDENT (spc);
275538fd1498Szrj 
275658e805e6Szrj 	      if (RECORD_OR_UNION_TYPE_P (typ) && !TREE_VISITED (stub))
275758e805e6Szrj 		dump_forward_type (buffer, typ, t, spc);
275838fd1498Szrj 
275938fd1498Szrj 	      pp_string (buffer, "subtype ");
276038fd1498Szrj 	      dump_ada_node (buffer, t, type, spc, false, true);
276138fd1498Szrj 	      pp_string (buffer, " is ");
276238fd1498Szrj 	      dump_ada_node (buffer, typ, type, spc, false, true);
276338fd1498Szrj 	      pp_string (buffer, ";  -- ");
276438fd1498Szrj 	      dump_sloc (buffer, t);
276538fd1498Szrj 
276638fd1498Szrj 	      TREE_VISITED (t) = 1;
276738fd1498Szrj 	      return 1;
276838fd1498Szrj 	    }
276938fd1498Szrj 	}
277038fd1498Szrj 
277138fd1498Szrj       /* Skip unnamed or anonymous structs/unions/enum types.  */
277238fd1498Szrj       if (!orig && !decl_name && !name
277338fd1498Szrj 	  && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
277438fd1498Szrj 	      || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE))
277538fd1498Szrj 	return 0;
277638fd1498Szrj 
277738fd1498Szrj 	/* Skip anonymous enum types (duplicates of real types).  */
277838fd1498Szrj       if (!orig
277938fd1498Szrj 	  && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE
278038fd1498Szrj 	  && decl_name
278138fd1498Szrj 	  && (*IDENTIFIER_POINTER (decl_name) == '.'
278238fd1498Szrj 	      || *IDENTIFIER_POINTER (decl_name) == '$'))
278338fd1498Szrj 	return 0;
278438fd1498Szrj 
278538fd1498Szrj       INDENT (spc);
278638fd1498Szrj 
278738fd1498Szrj       switch (TREE_CODE (TREE_TYPE (t)))
278838fd1498Szrj 	{
278938fd1498Szrj 	  case RECORD_TYPE:
279038fd1498Szrj 	  case UNION_TYPE:
279138fd1498Szrj 	    if (!COMPLETE_TYPE_P (TREE_TYPE (t)))
279238fd1498Szrj 	      {
279338fd1498Szrj 		pp_string (buffer, "type ");
279438fd1498Szrj 		dump_ada_node (buffer, t, type, spc, false, true);
279538fd1498Szrj 		pp_string (buffer, " is null record;   -- incomplete struct");
279638fd1498Szrj 		TREE_VISITED (t) = 1;
279738fd1498Szrj 		return 1;
279838fd1498Szrj 	      }
279938fd1498Szrj 
280038fd1498Szrj 	    if (decl_name
280138fd1498Szrj 		&& (*IDENTIFIER_POINTER (decl_name) == '.'
280238fd1498Szrj 		    || *IDENTIFIER_POINTER (decl_name) == '$'))
280338fd1498Szrj 	      {
280438fd1498Szrj 		pp_string (buffer, "--  skipped anonymous struct ");
280538fd1498Szrj 		dump_ada_node (buffer, t, type, spc, false, true);
280638fd1498Szrj 		TREE_VISITED (t) = 1;
280738fd1498Szrj 		return 1;
280838fd1498Szrj 	      }
280938fd1498Szrj 
281038fd1498Szrj 	    if (orig && TYPE_NAME (orig))
281138fd1498Szrj 	      pp_string (buffer, "subtype ");
281238fd1498Szrj 	    else
281338fd1498Szrj 	      {
281438fd1498Szrj 		dump_nested_types (buffer, t, t, spc);
281538fd1498Szrj 
281638fd1498Szrj                 if (separate_class_package (t))
281738fd1498Szrj 		  {
281838fd1498Szrj 		    is_class = true;
281938fd1498Szrj 		    pp_string (buffer, "package Class_");
282038fd1498Szrj 		    dump_ada_node (buffer, t, type, spc, false, true);
282138fd1498Szrj 		    pp_string (buffer, " is");
282238fd1498Szrj 		    spc += INDENT_INCR;
282338fd1498Szrj 		    newline_and_indent (buffer, spc);
282438fd1498Szrj 		  }
282538fd1498Szrj 
282638fd1498Szrj 		pp_string (buffer, "type ");
282738fd1498Szrj 	      }
282838fd1498Szrj 	    break;
282938fd1498Szrj 
283038fd1498Szrj 	  case POINTER_TYPE:
283138fd1498Szrj 	  case REFERENCE_TYPE:
283238fd1498Szrj 	    dump_forward_type (buffer, TREE_TYPE (TREE_TYPE (t)), t, spc);
283338fd1498Szrj 	    /* fallthrough */
283438fd1498Szrj 
283538fd1498Szrj 	  case ARRAY_TYPE:
283638fd1498Szrj 	    if ((orig && TYPE_NAME (orig)) || is_char_array (TREE_TYPE (t)))
283738fd1498Szrj 	      pp_string (buffer, "subtype ");
283838fd1498Szrj 	    else
283938fd1498Szrj 	      pp_string (buffer, "type ");
284038fd1498Szrj 	    break;
284138fd1498Szrj 
284238fd1498Szrj 	  case FUNCTION_TYPE:
284338fd1498Szrj 	    pp_string (buffer, "--  skipped function type ");
284438fd1498Szrj 	    dump_ada_node (buffer, t, type, spc, false, true);
284538fd1498Szrj 	    return 1;
284638fd1498Szrj 
284738fd1498Szrj 	  case ENUMERAL_TYPE:
284838fd1498Szrj 	    if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
284938fd1498Szrj 		|| !is_simple_enum (TREE_TYPE (t)))
285038fd1498Szrj 	      pp_string (buffer, "subtype ");
285138fd1498Szrj 	    else
285238fd1498Szrj 	      pp_string (buffer, "type ");
285338fd1498Szrj 	    break;
285438fd1498Szrj 
285538fd1498Szrj 	  default:
285638fd1498Szrj 	    pp_string (buffer, "subtype ");
285738fd1498Szrj 	}
285838fd1498Szrj       TREE_VISITED (t) = 1;
285938fd1498Szrj     }
286038fd1498Szrj   else
286138fd1498Szrj     {
286238fd1498Szrj       if (VAR_P (t)
286338fd1498Szrj 	  && decl_name
286438fd1498Szrj 	  && *IDENTIFIER_POINTER (decl_name) == '_')
286538fd1498Szrj 	return 0;
286638fd1498Szrj 
286738fd1498Szrj       need_indent = true;
286838fd1498Szrj     }
286938fd1498Szrj 
287038fd1498Szrj   /* Print the type and name.  */
287138fd1498Szrj   if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
287238fd1498Szrj     {
287338fd1498Szrj       if (need_indent)
287438fd1498Szrj 	INDENT (spc);
287538fd1498Szrj 
287638fd1498Szrj       /* Print variable's name.  */
287738fd1498Szrj       dump_ada_node (buffer, t, type, spc, false, true);
287838fd1498Szrj 
287938fd1498Szrj       if (TREE_CODE (t) == TYPE_DECL)
288038fd1498Szrj 	{
288138fd1498Szrj 	  pp_string (buffer, " is ");
288238fd1498Szrj 
288338fd1498Szrj 	  if (orig && TYPE_NAME (orig))
288438fd1498Szrj 	    dump_ada_node (buffer, TYPE_NAME (orig), type, spc, false, true);
288538fd1498Szrj 	  else
288638fd1498Szrj 	    dump_ada_array_type (buffer, TREE_TYPE (t), type, spc);
288738fd1498Szrj 	}
288838fd1498Szrj       else
288938fd1498Szrj 	{
289038fd1498Szrj 	  tree tmp = TYPE_NAME (TREE_TYPE (t));
289138fd1498Szrj 
289238fd1498Szrj 	  if (spc == INDENT_INCR || TREE_STATIC (t))
289338fd1498Szrj 	    is_var = true;
289438fd1498Szrj 
289538fd1498Szrj 	  pp_string (buffer, " : ");
289638fd1498Szrj 
289738fd1498Szrj 	  if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != POINTER_TYPE)
289838fd1498Szrj 	    pp_string (buffer, "aliased ");
289938fd1498Szrj 
290038fd1498Szrj 	  if (tmp)
290138fd1498Szrj 	    dump_ada_node (buffer, tmp, type, spc, false, true);
290238fd1498Szrj 	  else if (type)
290338fd1498Szrj 	    dump_ada_double_name (buffer, type, t);
290438fd1498Szrj 	  else
290538fd1498Szrj 	    dump_ada_array_type (buffer, TREE_TYPE (t), type, spc);
290638fd1498Szrj 	}
290738fd1498Szrj     }
290838fd1498Szrj   else if (TREE_CODE (t) == FUNCTION_DECL)
290938fd1498Szrj     {
291038fd1498Szrj       bool is_abstract_class = false;
291138fd1498Szrj       bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
291238fd1498Szrj       tree decl_name = DECL_NAME (t);
291338fd1498Szrj       bool is_abstract = false;
291438fd1498Szrj       bool is_constructor = false;
291538fd1498Szrj       bool is_destructor = false;
291638fd1498Szrj       bool is_copy_constructor = false;
291738fd1498Szrj       bool is_move_constructor = false;
291838fd1498Szrj 
291938fd1498Szrj       if (!decl_name)
292038fd1498Szrj 	return 0;
292138fd1498Szrj 
292238fd1498Szrj       if (cpp_check)
292338fd1498Szrj 	{
292438fd1498Szrj 	  is_abstract = cpp_check (t, IS_ABSTRACT);
292538fd1498Szrj 	  is_constructor = cpp_check (t, IS_CONSTRUCTOR);
292638fd1498Szrj 	  is_destructor = cpp_check (t, IS_DESTRUCTOR);
292738fd1498Szrj 	  is_copy_constructor = cpp_check (t, IS_COPY_CONSTRUCTOR);
292838fd1498Szrj 	  is_move_constructor = cpp_check (t, IS_MOVE_CONSTRUCTOR);
292938fd1498Szrj 	}
293038fd1498Szrj 
293138fd1498Szrj       /* Skip copy constructors and C++11 move constructors: some are internal
293238fd1498Szrj 	 only and those that are not cannot be called easily from Ada.  */
293338fd1498Szrj       if (is_copy_constructor || is_move_constructor)
293438fd1498Szrj 	return 0;
293538fd1498Szrj 
293638fd1498Szrj       if (is_constructor || is_destructor)
293738fd1498Szrj 	{
293838fd1498Szrj 	  /* ??? Skip implicit constructors/destructors for now.  */
293938fd1498Szrj 	  if (DECL_ARTIFICIAL (t))
294038fd1498Szrj 	    return 0;
294138fd1498Szrj 
2942*e215fc28Szrj 	  /* Only consider complete constructors and deleting destructors.  */
294338fd1498Szrj 	  if (strncmp (IDENTIFIER_POINTER (decl_name), "__ct_comp", 9) != 0
2944*e215fc28Szrj 	      && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_comp", 9) != 0
2945*e215fc28Szrj 	      && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_del", 8) != 0)
294638fd1498Szrj 	    return 0;
294738fd1498Szrj 	}
294838fd1498Szrj 
294938fd1498Szrj       /* If this function has an entry in the vtable, we cannot omit it.  */
295038fd1498Szrj       else if (!DECL_VINDEX (t) && *IDENTIFIER_POINTER (decl_name) == '_')
295138fd1498Szrj 	{
295238fd1498Szrj 	  INDENT (spc);
295338fd1498Szrj 	  pp_string (buffer, "--  skipped func ");
295438fd1498Szrj 	  pp_string (buffer, IDENTIFIER_POINTER (decl_name));
295538fd1498Szrj 	  return 1;
295638fd1498Szrj 	}
295738fd1498Szrj 
295838fd1498Szrj       if (need_indent)
295938fd1498Szrj 	INDENT (spc);
296038fd1498Szrj 
296138fd1498Szrj       if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && !is_constructor)
296238fd1498Szrj 	pp_string (buffer, "procedure ");
296338fd1498Szrj       else
296438fd1498Szrj 	pp_string (buffer, "function ");
296538fd1498Szrj 
296638fd1498Szrj       if (is_constructor)
296738fd1498Szrj 	print_constructor (buffer, t, type);
296838fd1498Szrj       else if (is_destructor)
296938fd1498Szrj 	print_destructor (buffer, t, type);
297038fd1498Szrj       else
297138fd1498Szrj 	dump_ada_decl_name (buffer, t, false);
297238fd1498Szrj 
297338fd1498Szrj       dump_ada_function_declaration
297438fd1498Szrj 	(buffer, t, is_method, is_constructor, is_destructor, spc);
297538fd1498Szrj 
297638fd1498Szrj       if (is_constructor && RECORD_OR_UNION_TYPE_P (type))
297738fd1498Szrj 	for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
297838fd1498Szrj 	  if (TREE_CODE (fld) == FUNCTION_DECL && cpp_check (fld, IS_ABSTRACT))
297938fd1498Szrj 	    {
298038fd1498Szrj 	      is_abstract_class = true;
298138fd1498Szrj 	      break;
298238fd1498Szrj 	    }
298338fd1498Szrj 
298438fd1498Szrj       if (is_abstract || is_abstract_class)
298538fd1498Szrj 	pp_string (buffer, " is abstract");
298638fd1498Szrj 
298738fd1498Szrj       pp_semicolon (buffer);
298838fd1498Szrj       pp_string (buffer, "  -- ");
298938fd1498Szrj       dump_sloc (buffer, t);
299038fd1498Szrj 
299138fd1498Szrj       if (is_abstract || !DECL_ASSEMBLER_NAME (t))
299238fd1498Szrj 	return 1;
299338fd1498Szrj 
299438fd1498Szrj       newline_and_indent (buffer, spc);
299538fd1498Szrj 
299638fd1498Szrj       if (is_constructor)
299738fd1498Szrj 	{
299838fd1498Szrj 	  pp_string (buffer, "pragma CPP_Constructor (");
299938fd1498Szrj 	  print_constructor (buffer, t, type);
300038fd1498Szrj 	  pp_string (buffer, ", \"");
300138fd1498Szrj 	  pp_asm_name (buffer, t);
300238fd1498Szrj 	  pp_string (buffer, "\");");
300338fd1498Szrj 	}
300438fd1498Szrj       else if (is_destructor)
300538fd1498Szrj 	{
300638fd1498Szrj 	  pp_string (buffer, "pragma Import (CPP, ");
300738fd1498Szrj 	  print_destructor (buffer, t, type);
300838fd1498Szrj 	  pp_string (buffer, ", \"");
300938fd1498Szrj 	  pp_asm_name (buffer, t);
301038fd1498Szrj 	  pp_string (buffer, "\");");
301138fd1498Szrj 	}
301238fd1498Szrj       else
301338fd1498Szrj 	dump_ada_import (buffer, t);
301438fd1498Szrj 
301538fd1498Szrj       return 1;
301638fd1498Szrj     }
301738fd1498Szrj   else if (TREE_CODE (t) == TYPE_DECL && !orig)
301838fd1498Szrj     {
301938fd1498Szrj       bool is_interface = false;
302038fd1498Szrj       bool is_abstract_record = false;
302138fd1498Szrj 
302238fd1498Szrj       if (need_indent)
302338fd1498Szrj 	INDENT (spc);
302438fd1498Szrj 
302538fd1498Szrj       /* Anonymous structs/unions.  */
302638fd1498Szrj       dump_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
302738fd1498Szrj 
302838fd1498Szrj       if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
302938fd1498Szrj 	pp_string (buffer, " (discr : unsigned := 0)");
303038fd1498Szrj 
303138fd1498Szrj       pp_string (buffer, " is ");
303238fd1498Szrj 
303338fd1498Szrj       /* Check whether we have an Ada interface compatible class.
303438fd1498Szrj 	 That is only have a vtable non-static data member and no
303538fd1498Szrj 	 non-abstract methods.  */
303638fd1498Szrj       if (cpp_check
303738fd1498Szrj 	  && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
303838fd1498Szrj 	{
303938fd1498Szrj 	  bool has_fields = false;
304038fd1498Szrj 
304138fd1498Szrj 	  /* Check that there are no fields other than the virtual table.  */
304238fd1498Szrj 	  for (tree fld = TYPE_FIELDS (TREE_TYPE (t));
304338fd1498Szrj 	       fld;
304438fd1498Szrj 	       fld = TREE_CHAIN (fld))
304538fd1498Szrj 	    {
304638fd1498Szrj 	      if (TREE_CODE (fld) == FIELD_DECL)
304738fd1498Szrj 		{
304838fd1498Szrj 		  if (!has_fields && DECL_VIRTUAL_P (fld))
304938fd1498Szrj 		    is_interface = true;
305038fd1498Szrj 		  else
305138fd1498Szrj 		    is_interface = false;
305238fd1498Szrj 		  has_fields = true;
305338fd1498Szrj 		}
305438fd1498Szrj 	      else if (TREE_CODE (fld) == FUNCTION_DECL
305538fd1498Szrj 		       && !DECL_ARTIFICIAL (fld))
305638fd1498Szrj 		{
305738fd1498Szrj 		  if (cpp_check (fld, IS_ABSTRACT))
305838fd1498Szrj 		    is_abstract_record = true;
305938fd1498Szrj 		  else
306038fd1498Szrj 		    is_interface = false;
306138fd1498Szrj 		}
306238fd1498Szrj 	    }
306338fd1498Szrj 	}
306438fd1498Szrj 
306538fd1498Szrj       TREE_VISITED (t) = 1;
306638fd1498Szrj       if (is_interface)
306738fd1498Szrj 	{
306838fd1498Szrj 	  pp_string (buffer, "limited interface;  -- ");
306938fd1498Szrj 	  dump_sloc (buffer, t);
307038fd1498Szrj 	  newline_and_indent (buffer, spc);
307138fd1498Szrj 	  pp_string (buffer, "pragma Import (CPP, ");
307238fd1498Szrj 	  dump_ada_node (buffer, TYPE_NAME (TREE_TYPE (t)), type, spc, false,
307338fd1498Szrj 			 true);
307438fd1498Szrj 	  pp_right_paren (buffer);
307538fd1498Szrj 
307638fd1498Szrj 	  dump_ada_methods (buffer, TREE_TYPE (t), spc);
307738fd1498Szrj 	}
307838fd1498Szrj       else
307938fd1498Szrj 	{
308038fd1498Szrj 	  if (is_abstract_record)
308138fd1498Szrj 	    pp_string (buffer, "abstract ");
308238fd1498Szrj 	  dump_ada_node (buffer, t, t, spc, false, false);
308338fd1498Szrj 	}
308438fd1498Szrj     }
308538fd1498Szrj   else
308638fd1498Szrj     {
308738fd1498Szrj       if (need_indent)
308838fd1498Szrj 	INDENT (spc);
308938fd1498Szrj 
309038fd1498Szrj       if (TREE_CODE (t) == FIELD_DECL && DECL_NAME (t))
309138fd1498Szrj 	check_name (buffer, t);
309238fd1498Szrj 
309338fd1498Szrj       /* Print variable/type's name.  */
309438fd1498Szrj       dump_ada_node (buffer, t, t, spc, false, true);
309538fd1498Szrj 
309638fd1498Szrj       if (TREE_CODE (t) == TYPE_DECL)
309738fd1498Szrj 	{
309838fd1498Szrj 	  const bool is_subtype = TYPE_NAME (orig);
309938fd1498Szrj 
310038fd1498Szrj 	  if (!is_subtype && TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
310138fd1498Szrj 	    pp_string (buffer, " (discr : unsigned := 0)");
310238fd1498Szrj 
310338fd1498Szrj 	  pp_string (buffer, " is ");
310438fd1498Szrj 
310538fd1498Szrj 	  dump_ada_node (buffer, orig, t, spc, false, is_subtype);
310638fd1498Szrj 	}
310738fd1498Szrj       else
310838fd1498Szrj 	{
310938fd1498Szrj 	  if (spc == INDENT_INCR || TREE_STATIC (t))
311038fd1498Szrj 	    is_var = true;
311138fd1498Szrj 
311238fd1498Szrj 	  pp_string (buffer, " : ");
311338fd1498Szrj 
311438fd1498Szrj 	  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
311538fd1498Szrj 	      || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
311638fd1498Szrj 	    {
311738fd1498Szrj 	      if (TYPE_NAME (TREE_TYPE (t))
311838fd1498Szrj 		  || TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE)
311938fd1498Szrj 		pp_string (buffer, "aliased ");
312038fd1498Szrj 
312138fd1498Szrj 	      if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL)
312238fd1498Szrj 		pp_string (buffer, "constant ");
312338fd1498Szrj 
312438fd1498Szrj 	      if (TYPE_NAME (TREE_TYPE (t)))
312538fd1498Szrj 		dump_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
312638fd1498Szrj 	      else if (type)
312738fd1498Szrj 		dump_ada_double_name (buffer, type, t);
312838fd1498Szrj 	    }
312938fd1498Szrj 	  else
313038fd1498Szrj 	    {
313138fd1498Szrj 	      if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
313238fd1498Szrj 		  && (TYPE_NAME (TREE_TYPE (t))
313338fd1498Szrj 		      || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE))
313438fd1498Szrj 		pp_string (buffer, "aliased ");
313538fd1498Szrj 
313638fd1498Szrj 	      if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL)
313738fd1498Szrj 		pp_string (buffer, "constant ");
313838fd1498Szrj 
313938fd1498Szrj 	      dump_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
314038fd1498Szrj 	    }
314138fd1498Szrj 	}
314238fd1498Szrj     }
314338fd1498Szrj 
314438fd1498Szrj   if (is_class)
314538fd1498Szrj     {
314638fd1498Szrj       spc -= INDENT_INCR;
314738fd1498Szrj       newline_and_indent (buffer, spc);
314838fd1498Szrj       pp_string (buffer, "end;");
314938fd1498Szrj       newline_and_indent (buffer, spc);
315038fd1498Szrj       pp_string (buffer, "use Class_");
315138fd1498Szrj       dump_ada_node (buffer, t, type, spc, false, true);
315238fd1498Szrj       pp_semicolon (buffer);
315338fd1498Szrj       pp_newline (buffer);
315438fd1498Szrj 
315538fd1498Szrj       /* All needed indentation/newline performed already, so return 0.  */
315638fd1498Szrj       return 0;
315738fd1498Szrj     }
315838fd1498Szrj   else
315938fd1498Szrj     {
316038fd1498Szrj       pp_string (buffer, ";  -- ");
316138fd1498Szrj       dump_sloc (buffer, t);
316238fd1498Szrj     }
316338fd1498Szrj 
316438fd1498Szrj   if (is_var)
316538fd1498Szrj     {
316638fd1498Szrj       newline_and_indent (buffer, spc);
316738fd1498Szrj       dump_ada_import (buffer, t);
316838fd1498Szrj     }
316938fd1498Szrj 
317038fd1498Szrj   return 1;
317138fd1498Szrj }
317238fd1498Szrj 
317338fd1498Szrj /* Dump in BUFFER a structure NODE of type TYPE: name, fields, and methods
317438fd1498Szrj    in Ada syntax.  SPC is the indentation level.  If DISPLAY_CONVENTION is
317538fd1498Szrj    true, also print the pragma Convention for NODE.  */
317638fd1498Szrj 
317738fd1498Szrj static void
dump_ada_structure(pretty_printer * buffer,tree node,tree type,int spc,bool display_convention)317838fd1498Szrj dump_ada_structure (pretty_printer *buffer, tree node, tree type, int spc,
317938fd1498Szrj 		    bool display_convention)
318038fd1498Szrj {
318138fd1498Szrj   const bool is_union = (TREE_CODE (node) == UNION_TYPE);
318238fd1498Szrj   char buf[32];
318338fd1498Szrj   int field_num = 0;
318438fd1498Szrj   int field_spc = spc + INDENT_INCR;
318538fd1498Szrj   int need_semicolon;
318638fd1498Szrj 
318738fd1498Szrj   bitfield_used = false;
318838fd1498Szrj 
318938fd1498Szrj   /* Print the contents of the structure.  */
319038fd1498Szrj   pp_string (buffer, "record");
319138fd1498Szrj 
319238fd1498Szrj   if (is_union)
319338fd1498Szrj     {
319438fd1498Szrj       newline_and_indent (buffer, spc + INDENT_INCR);
319538fd1498Szrj       pp_string (buffer, "case discr is");
319638fd1498Szrj       field_spc = spc + INDENT_INCR * 3;
319738fd1498Szrj     }
319838fd1498Szrj 
319938fd1498Szrj   pp_newline (buffer);
320038fd1498Szrj 
320138fd1498Szrj   /* Print the non-static fields of the structure.  */
320238fd1498Szrj   for (tree tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
320338fd1498Szrj     {
320438fd1498Szrj       /* Add parent field if needed.  */
320538fd1498Szrj       if (!DECL_NAME (tmp))
320638fd1498Szrj 	{
320738fd1498Szrj 	  if (!is_tagged_type (TREE_TYPE (tmp)))
320838fd1498Szrj 	    {
320938fd1498Szrj 	      if (!TYPE_NAME (TREE_TYPE (tmp)))
321038fd1498Szrj 		dump_ada_declaration (buffer, tmp, type, field_spc);
321138fd1498Szrj 	      else
321238fd1498Szrj 		{
321338fd1498Szrj 		  INDENT (field_spc);
321438fd1498Szrj 
321538fd1498Szrj 		  if (field_num == 0)
321638fd1498Szrj 		    pp_string (buffer, "parent : aliased ");
321738fd1498Szrj 		  else
321838fd1498Szrj 		    {
321938fd1498Szrj 		      sprintf (buf, "field_%d : aliased ", field_num + 1);
322038fd1498Szrj 		      pp_string (buffer, buf);
322138fd1498Szrj 		    }
322238fd1498Szrj 		  dump_ada_decl_name (buffer, TYPE_NAME (TREE_TYPE (tmp)),
322338fd1498Szrj 				      false);
322438fd1498Szrj 		  pp_semicolon (buffer);
322538fd1498Szrj 		}
322638fd1498Szrj 
322738fd1498Szrj 	      pp_newline (buffer);
322838fd1498Szrj 	      field_num++;
322938fd1498Szrj 	    }
323038fd1498Szrj 	}
323138fd1498Szrj       else if (TREE_CODE (tmp) == FIELD_DECL)
323238fd1498Szrj 	{
323338fd1498Szrj 	  /* Skip internal virtual table field.  */
323438fd1498Szrj 	  if (!DECL_VIRTUAL_P (tmp))
323538fd1498Szrj 	    {
323638fd1498Szrj 	      if (is_union)
323738fd1498Szrj 		{
323838fd1498Szrj 		  if (TREE_CHAIN (tmp)
323938fd1498Szrj 		      && TREE_TYPE (TREE_CHAIN (tmp)) != node
324038fd1498Szrj 		      && TREE_CODE (TREE_CHAIN (tmp)) != TYPE_DECL)
324138fd1498Szrj 		    sprintf (buf, "when %d =>", field_num);
324238fd1498Szrj 		  else
324338fd1498Szrj 		    sprintf (buf, "when others =>");
324438fd1498Szrj 
324538fd1498Szrj 		  INDENT (spc + INDENT_INCR * 2);
324638fd1498Szrj 		  pp_string (buffer, buf);
324738fd1498Szrj 		  pp_newline (buffer);
324838fd1498Szrj 		}
324938fd1498Szrj 
325038fd1498Szrj 	      if (dump_ada_declaration (buffer, tmp, type, field_spc))
325138fd1498Szrj 		{
325238fd1498Szrj 		  pp_newline (buffer);
325338fd1498Szrj 		  field_num++;
325438fd1498Szrj 		}
325538fd1498Szrj 	    }
325638fd1498Szrj 	}
325738fd1498Szrj     }
325838fd1498Szrj 
325938fd1498Szrj   if (is_union)
326038fd1498Szrj     {
326138fd1498Szrj       INDENT (spc + INDENT_INCR);
326238fd1498Szrj       pp_string (buffer, "end case;");
326338fd1498Szrj       pp_newline (buffer);
326438fd1498Szrj     }
326538fd1498Szrj 
326638fd1498Szrj   if (field_num == 0)
326738fd1498Szrj     {
326838fd1498Szrj       INDENT (spc + INDENT_INCR);
326938fd1498Szrj       pp_string (buffer, "null;");
327038fd1498Szrj       pp_newline (buffer);
327138fd1498Szrj     }
327238fd1498Szrj 
327338fd1498Szrj   INDENT (spc);
327438fd1498Szrj   pp_string (buffer, "end record;");
327538fd1498Szrj 
327638fd1498Szrj   newline_and_indent (buffer, spc);
327738fd1498Szrj 
327838fd1498Szrj   if (!display_convention)
327938fd1498Szrj     return;
328038fd1498Szrj 
328138fd1498Szrj   if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
328238fd1498Szrj     {
328338fd1498Szrj       if (has_nontrivial_methods (TREE_TYPE (type)))
328438fd1498Szrj 	pp_string (buffer, "pragma Import (CPP, ");
328538fd1498Szrj       else
328638fd1498Szrj 	pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
328738fd1498Szrj     }
328838fd1498Szrj   else
328938fd1498Szrj     pp_string (buffer, "pragma Convention (C, ");
329038fd1498Szrj 
329138fd1498Szrj   package_prefix = false;
329238fd1498Szrj   dump_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
329338fd1498Szrj   package_prefix = true;
329438fd1498Szrj   pp_right_paren (buffer);
329538fd1498Szrj 
329638fd1498Szrj   if (is_union)
329738fd1498Szrj     {
329838fd1498Szrj       pp_semicolon (buffer);
329938fd1498Szrj       newline_and_indent (buffer, spc);
330038fd1498Szrj       pp_string (buffer, "pragma Unchecked_Union (");
330138fd1498Szrj 
330238fd1498Szrj       dump_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
330338fd1498Szrj       pp_right_paren (buffer);
330438fd1498Szrj     }
330538fd1498Szrj 
330638fd1498Szrj   if (bitfield_used)
330738fd1498Szrj     {
330838fd1498Szrj       pp_semicolon (buffer);
330938fd1498Szrj       newline_and_indent (buffer, spc);
331038fd1498Szrj       pp_string (buffer, "pragma Pack (");
331138fd1498Szrj       dump_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
331238fd1498Szrj       pp_right_paren (buffer);
331338fd1498Szrj       bitfield_used = false;
331438fd1498Szrj     }
331538fd1498Szrj 
331638fd1498Szrj   need_semicolon = !dump_ada_methods (buffer, node, spc);
331738fd1498Szrj 
331838fd1498Szrj   /* Print the static fields of the structure, if any.  */
331938fd1498Szrj   for (tree tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
332038fd1498Szrj     {
332138fd1498Szrj       if (TREE_CODE (tmp) == VAR_DECL && DECL_NAME (tmp))
332238fd1498Szrj 	{
332338fd1498Szrj 	  if (need_semicolon)
332438fd1498Szrj 	    {
332538fd1498Szrj 	      need_semicolon = false;
332638fd1498Szrj 	      pp_semicolon (buffer);
332738fd1498Szrj 	    }
332838fd1498Szrj 	  pp_newline (buffer);
332938fd1498Szrj 	  pp_newline (buffer);
333038fd1498Szrj 	  dump_ada_declaration (buffer, tmp, type, spc);
333138fd1498Szrj 	}
333238fd1498Szrj     }
333338fd1498Szrj }
333438fd1498Szrj 
333538fd1498Szrj /* Dump all the declarations in SOURCE_FILE to an Ada spec.
333638fd1498Szrj    COLLECT_ALL_REFS is a front-end callback used to collect all relevant
333738fd1498Szrj    nodes for SOURCE_FILE.  CHECK is used to perform C++ queries on nodes.  */
333838fd1498Szrj 
333938fd1498Szrj static void
dump_ads(const char * source_file,void (* collect_all_refs)(const char *),int (* check)(tree,cpp_operation))334038fd1498Szrj dump_ads (const char *source_file,
334138fd1498Szrj 	  void (*collect_all_refs)(const char *),
334238fd1498Szrj 	  int (*check)(tree, cpp_operation))
334338fd1498Szrj {
334438fd1498Szrj   char *ads_name;
334538fd1498Szrj   char *pkg_name;
334638fd1498Szrj   char *s;
334738fd1498Szrj   FILE *f;
334838fd1498Szrj 
334938fd1498Szrj   pkg_name = get_ada_package (source_file);
335038fd1498Szrj 
335138fd1498Szrj   /* Construct the .ads filename and package name.  */
335238fd1498Szrj   ads_name = xstrdup (pkg_name);
335338fd1498Szrj 
335438fd1498Szrj   for (s = ads_name; *s; s++)
335538fd1498Szrj     if (*s == '.')
335638fd1498Szrj       *s = '-';
335738fd1498Szrj     else
335838fd1498Szrj       *s = TOLOWER (*s);
335938fd1498Szrj 
336038fd1498Szrj   ads_name = reconcat (ads_name, ads_name, ".ads", NULL);
336138fd1498Szrj 
336238fd1498Szrj   /* Write out the .ads file.  */
336338fd1498Szrj   f = fopen (ads_name, "w");
336438fd1498Szrj   if (f)
336538fd1498Szrj     {
336638fd1498Szrj       pretty_printer pp;
336738fd1498Szrj 
336838fd1498Szrj       pp_needs_newline (&pp) = true;
336938fd1498Szrj       pp.buffer->stream = f;
337038fd1498Szrj 
337138fd1498Szrj       /* Dump all relevant macros.  */
337238fd1498Szrj       dump_ada_macros (&pp, source_file);
337338fd1498Szrj 
337438fd1498Szrj       /* Reset the table of withs for this file.  */
337538fd1498Szrj       reset_ada_withs ();
337638fd1498Szrj 
337738fd1498Szrj       (*collect_all_refs) (source_file);
337838fd1498Szrj 
337938fd1498Szrj       /* Dump all references.  */
338038fd1498Szrj       cpp_check = check;
338138fd1498Szrj       dump_ada_nodes (&pp, source_file);
338238fd1498Szrj 
338338fd1498Szrj       /* Requires Ada 2005 syntax, so generate corresponding pragma.
338438fd1498Szrj          Also, disable style checks since this file is auto-generated.  */
338538fd1498Szrj       fprintf (f, "pragma Ada_2005;\npragma Style_Checks (Off);\n\n");
338638fd1498Szrj 
338738fd1498Szrj       /* Dump withs.  */
338838fd1498Szrj       dump_ada_withs (f);
338938fd1498Szrj 
339038fd1498Szrj       fprintf (f, "\npackage %s is\n\n", pkg_name);
339138fd1498Szrj       pp_write_text_to_stream (&pp);
339238fd1498Szrj       /* ??? need to free pp */
339338fd1498Szrj       fprintf (f, "end %s;\n", pkg_name);
339438fd1498Szrj       fclose (f);
339538fd1498Szrj     }
339638fd1498Szrj 
339738fd1498Szrj   free (ads_name);
339838fd1498Szrj   free (pkg_name);
339938fd1498Szrj }
340038fd1498Szrj 
340138fd1498Szrj static const char **source_refs = NULL;
340238fd1498Szrj static int source_refs_used = 0;
340338fd1498Szrj static int source_refs_allocd = 0;
340438fd1498Szrj 
340538fd1498Szrj /* Add an entry for FILENAME to the table SOURCE_REFS.  */
340638fd1498Szrj 
340738fd1498Szrj void
collect_source_ref(const char * filename)340838fd1498Szrj collect_source_ref (const char *filename)
340938fd1498Szrj {
341038fd1498Szrj   int i;
341138fd1498Szrj 
341238fd1498Szrj   if (!filename)
341338fd1498Szrj     return;
341438fd1498Szrj 
341538fd1498Szrj   if (source_refs_allocd == 0)
341638fd1498Szrj     {
341738fd1498Szrj       source_refs_allocd = 1024;
341838fd1498Szrj       source_refs = XNEWVEC (const char *, source_refs_allocd);
341938fd1498Szrj     }
342038fd1498Szrj 
342138fd1498Szrj   for (i = 0; i < source_refs_used; i++)
342238fd1498Szrj     if (filename == source_refs[i])
342338fd1498Szrj       return;
342438fd1498Szrj 
342538fd1498Szrj   if (source_refs_used == source_refs_allocd)
342638fd1498Szrj     {
342738fd1498Szrj       source_refs_allocd *= 2;
342838fd1498Szrj       source_refs = XRESIZEVEC (const char *, source_refs, source_refs_allocd);
342938fd1498Szrj     }
343038fd1498Szrj 
343138fd1498Szrj   source_refs[source_refs_used++] = filename;
343238fd1498Szrj }
343338fd1498Szrj 
343438fd1498Szrj /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
343538fd1498Szrj    using callbacks COLLECT_ALL_REFS and CHECK.
343638fd1498Szrj    COLLECT_ALL_REFS is a front-end callback used to collect all relevant
343738fd1498Szrj    nodes for a given source file.
343838fd1498Szrj    CHECK is used to perform C++ queries on nodes, or NULL for the C
343938fd1498Szrj    front-end.  */
344038fd1498Szrj 
344138fd1498Szrj void
dump_ada_specs(void (* collect_all_refs)(const char *),int (* check)(tree,cpp_operation))344238fd1498Szrj dump_ada_specs (void (*collect_all_refs)(const char *),
344338fd1498Szrj 		int (*check)(tree, cpp_operation))
344438fd1498Szrj {
344538fd1498Szrj   /* Iterate over the list of files to dump specs for.  */
344638fd1498Szrj   for (int i = 0; i < source_refs_used; i++)
344738fd1498Szrj     dump_ads (source_refs[i], collect_all_refs, check);
344838fd1498Szrj 
344938fd1498Szrj   /* Free various tables.  */
345038fd1498Szrj   free (source_refs);
345138fd1498Szrj   delete overloaded_names;
345238fd1498Szrj }
3453