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 = ¯o->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, ¶m_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 = ¯o->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