PR target/41993
[official-gcc.git] / gcc / c-family / c-ada-spec.c
blob4c47ed44a549b244ffc9ac4f0ae13bb420aacf1a
1 /* Print GENERIC declaration (functions, variables, types) trees coming from
2 the C and C++ front-ends as well as macros in Ada syntax.
3 Copyright (C) 2010 Free Software Foundation, Inc.
4 Adapted from tree-pretty-print.c by Arnaud Charlet <charlet@adacore.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "dumpfile.h"
28 #include "c-ada-spec.h"
29 #include "cpplib.h"
30 #include "c-pragma.h"
31 #include "cpp-id-data.h"
33 /* Adapted from hwint.h to use the Ada prefix. */
34 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
35 # if HOST_BITS_PER_WIDE_INT == 64
36 # define ADA_HOST_WIDE_INT_PRINT_DOUBLE_HEX \
37 "16#%" HOST_LONG_FORMAT "x%016" HOST_LONG_FORMAT "x#"
38 # else
39 # define ADA_HOST_WIDE_INT_PRINT_DOUBLE_HEX \
40 "16#%" HOST_LONG_FORMAT "x%08" HOST_LONG_FORMAT "x#"
41 # endif
42 #else
43 /* We can assume that 'long long' is at least 64 bits. */
44 # define ADA_HOST_WIDE_INT_PRINT_DOUBLE_HEX \
45 "16#%" HOST_LONG_LONG_FORMAT "x%016" HOST_LONG_LONG_FORMAT "x#"
46 #endif /* HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG */
48 /* Local functions, macros and variables. */
49 static int dump_generic_ada_node (pretty_printer *, tree, tree,
50 int (*)(tree, cpp_operation), int, int, bool);
51 static int print_ada_declaration (pretty_printer *, tree, tree,
52 int (*cpp_check)(tree, cpp_operation), int);
53 static void print_ada_struct_decl (pretty_printer *, tree, tree,
54 int (*cpp_check)(tree, cpp_operation), int,
55 bool);
56 static void dump_sloc (pretty_printer *buffer, tree node);
57 static void print_comment (pretty_printer *, const char *);
58 static void print_generic_ada_decl (pretty_printer *, tree,
59 int (*)(tree, cpp_operation), const char *);
60 static char *get_ada_package (const char *);
61 static void dump_ada_nodes (pretty_printer *, const char *,
62 int (*)(tree, cpp_operation));
63 static void reset_ada_withs (void);
64 static void dump_ada_withs (FILE *);
65 static void dump_ads (const char *, void (*)(const char *),
66 int (*)(tree, cpp_operation));
67 static char *to_ada_name (const char *, int *);
68 static bool separate_class_package (tree);
70 #define INDENT(SPACE) do { \
71 int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
73 #define INDENT_INCR 3
75 /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
76 as max length PARAM_LEN of arguments for fun_like macros, and also set
77 SUPPORTED to 0 if the macro cannot be mapped to an Ada construct. */
79 static void
80 macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
81 int *param_len)
83 int i;
84 unsigned j;
86 *supported = 1;
87 *buffer_len = 0;
88 *param_len = 0;
90 if (macro->fun_like)
92 param_len++;
93 for (i = 0; i < macro->paramc; i++)
95 cpp_hashnode *param = macro->params[i];
97 *param_len += NODE_LEN (param);
99 if (i + 1 < macro->paramc)
101 *param_len += 2; /* ", " */
103 else if (macro->variadic)
105 *supported = 0;
106 return;
109 *param_len += 2; /* ")\0" */
112 for (j = 0; j < macro->count; j++)
114 cpp_token *token = &macro->exp.tokens[j];
116 if (token->flags & PREV_WHITE)
117 (*buffer_len)++;
119 if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
121 *supported = 0;
122 return;
125 if (token->type == CPP_MACRO_ARG)
126 *buffer_len +=
127 NODE_LEN (macro->params[token->val.macro_arg.arg_no - 1]);
128 else
129 /* Include enough extra space to handle e.g. special characters. */
130 *buffer_len += (cpp_token_len (token) + 1) * 8;
133 (*buffer_len)++;
136 /* Dump into PP a set of MAX_ADA_MACROS MACROS (C/C++) as Ada constants when
137 possible. */
139 static void
140 print_ada_macros (pretty_printer *pp, cpp_hashnode **macros, int max_ada_macros)
142 int j, num_macros = 0, prev_line = -1;
144 for (j = 0; j < max_ada_macros; j++)
146 cpp_hashnode *node = macros[j];
147 const cpp_macro *macro = node->value.macro;
148 unsigned i;
149 int supported = 1, prev_is_one = 0, buffer_len, param_len;
150 int is_string = 0, is_char = 0;
151 char *ada_name;
152 unsigned char *s, *params, *buffer, *buf_param, *char_one = NULL;
154 macro_length (macro, &supported, &buffer_len, &param_len);
155 s = buffer = XALLOCAVEC (unsigned char, buffer_len);
156 params = buf_param = XALLOCAVEC (unsigned char, param_len);
158 if (supported)
160 if (macro->fun_like)
162 *buf_param++ = '(';
163 for (i = 0; i < macro->paramc; i++)
165 cpp_hashnode *param = macro->params[i];
167 memcpy (buf_param, NODE_NAME (param), NODE_LEN (param));
168 buf_param += NODE_LEN (param);
170 if (i + 1 < macro->paramc)
172 *buf_param++ = ',';
173 *buf_param++ = ' ';
175 else if (macro->variadic)
177 supported = 0;
178 break;
181 *buf_param++ = ')';
182 *buf_param = '\0';
185 for (i = 0; supported && i < macro->count; i++)
187 cpp_token *token = &macro->exp.tokens[i];
188 int is_one = 0;
190 if (token->flags & PREV_WHITE)
191 *buffer++ = ' ';
193 if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
195 supported = 0;
196 break;
199 switch (token->type)
201 case CPP_MACRO_ARG:
203 cpp_hashnode *param =
204 macro->params[token->val.macro_arg.arg_no - 1];
205 memcpy (buffer, NODE_NAME (param), NODE_LEN (param));
206 buffer += NODE_LEN (param);
208 break;
210 case CPP_EQ_EQ: *buffer++ = '='; break;
211 case CPP_GREATER: *buffer++ = '>'; break;
212 case CPP_LESS: *buffer++ = '<'; break;
213 case CPP_PLUS: *buffer++ = '+'; break;
214 case CPP_MINUS: *buffer++ = '-'; break;
215 case CPP_MULT: *buffer++ = '*'; break;
216 case CPP_DIV: *buffer++ = '/'; break;
217 case CPP_COMMA: *buffer++ = ','; break;
218 case CPP_OPEN_SQUARE:
219 case CPP_OPEN_PAREN: *buffer++ = '('; break;
220 case CPP_CLOSE_SQUARE: /* fallthrough */
221 case CPP_CLOSE_PAREN: *buffer++ = ')'; break;
222 case CPP_DEREF: /* fallthrough */
223 case CPP_SCOPE: /* fallthrough */
224 case CPP_DOT: *buffer++ = '.'; break;
226 case CPP_EQ: *buffer++ = ':'; *buffer++ = '='; break;
227 case CPP_NOT_EQ: *buffer++ = '/'; *buffer++ = '='; break;
228 case CPP_GREATER_EQ: *buffer++ = '>'; *buffer++ = '='; break;
229 case CPP_LESS_EQ: *buffer++ = '<'; *buffer++ = '='; break;
231 case CPP_NOT:
232 *buffer++ = 'n'; *buffer++ = 'o'; *buffer++ = 't'; break;
233 case CPP_MOD:
234 *buffer++ = 'm'; *buffer++ = 'o'; *buffer++ = 'd'; break;
235 case CPP_AND:
236 *buffer++ = 'a'; *buffer++ = 'n'; *buffer++ = 'd'; break;
237 case CPP_OR:
238 *buffer++ = 'o'; *buffer++ = 'r'; break;
239 case CPP_XOR:
240 *buffer++ = 'x'; *buffer++ = 'o'; *buffer++ = 'r'; break;
241 case CPP_AND_AND:
242 strcpy ((char *) buffer, " and then ");
243 buffer += 10;
244 break;
245 case CPP_OR_OR:
246 strcpy ((char *) buffer, " or else ");
247 buffer += 9;
248 break;
250 case CPP_PADDING:
251 *buffer++ = ' ';
252 is_one = prev_is_one;
253 break;
255 case CPP_COMMENT: break;
257 case CPP_WSTRING:
258 case CPP_STRING16:
259 case CPP_STRING32:
260 case CPP_UTF8STRING:
261 case CPP_WCHAR:
262 case CPP_CHAR16:
263 case CPP_CHAR32:
264 case CPP_NAME:
265 case CPP_STRING:
266 case CPP_NUMBER:
267 if (!macro->fun_like)
268 supported = 0;
269 else
270 buffer = cpp_spell_token (parse_in, token, buffer, false);
271 break;
273 case CPP_CHAR:
274 is_char = 1;
276 unsigned chars_seen;
277 int ignored;
278 cppchar_t c;
280 c = cpp_interpret_charconst (parse_in, token,
281 &chars_seen, &ignored);
282 if (c >= 32 && c <= 126)
284 *buffer++ = '\'';
285 *buffer++ = (char) c;
286 *buffer++ = '\'';
288 else
290 chars_seen = sprintf
291 ((char *) buffer, "Character'Val (%d)", (int) c);
292 buffer += chars_seen;
295 break;
297 case CPP_LSHIFT:
298 if (prev_is_one)
300 /* Replace "1 << N" by "2 ** N" */
301 *char_one = '2';
302 *buffer++ = '*';
303 *buffer++ = '*';
304 break;
306 /* fallthrough */
308 case CPP_RSHIFT:
309 case CPP_COMPL:
310 case CPP_QUERY:
311 case CPP_EOF:
312 case CPP_PLUS_EQ:
313 case CPP_MINUS_EQ:
314 case CPP_MULT_EQ:
315 case CPP_DIV_EQ:
316 case CPP_MOD_EQ:
317 case CPP_AND_EQ:
318 case CPP_OR_EQ:
319 case CPP_XOR_EQ:
320 case CPP_RSHIFT_EQ:
321 case CPP_LSHIFT_EQ:
322 case CPP_PRAGMA:
323 case CPP_PRAGMA_EOL:
324 case CPP_HASH:
325 case CPP_PASTE:
326 case CPP_OPEN_BRACE:
327 case CPP_CLOSE_BRACE:
328 case CPP_SEMICOLON:
329 case CPP_ELLIPSIS:
330 case CPP_PLUS_PLUS:
331 case CPP_MINUS_MINUS:
332 case CPP_DEREF_STAR:
333 case CPP_DOT_STAR:
334 case CPP_ATSIGN:
335 case CPP_HEADER_NAME:
336 case CPP_AT_NAME:
337 case CPP_OTHER:
338 case CPP_OBJC_STRING:
339 default:
340 if (!macro->fun_like)
341 supported = 0;
342 else
343 buffer = cpp_spell_token (parse_in, token, buffer, false);
344 break;
347 prev_is_one = is_one;
350 if (supported)
351 *buffer = '\0';
354 if (macro->fun_like && supported)
356 char *start = (char *) s;
357 int is_function = 0;
359 pp_string (pp, " -- arg-macro: ");
361 if (*start == '(' && buffer[-1] == ')')
363 start++;
364 buffer[-1] = '\0';
365 is_function = 1;
366 pp_string (pp, "function ");
368 else
370 pp_string (pp, "procedure ");
373 pp_string (pp, (const char *) NODE_NAME (node));
374 pp_space (pp);
375 pp_string (pp, (char *) params);
376 pp_newline (pp);
377 pp_string (pp, " -- ");
379 if (is_function)
381 pp_string (pp, "return ");
382 pp_string (pp, start);
383 pp_semicolon (pp);
385 else
386 pp_string (pp, start);
388 pp_newline (pp);
390 else if (supported)
392 expanded_location sloc = expand_location (macro->line);
394 if (sloc.line != prev_line + 1)
395 pp_newline (pp);
397 num_macros++;
398 prev_line = sloc.line;
400 pp_string (pp, " ");
401 ada_name = to_ada_name ((const char *) NODE_NAME (node), NULL);
402 pp_string (pp, ada_name);
403 free (ada_name);
404 pp_string (pp, " : ");
406 if (is_string)
407 pp_string (pp, "aliased constant String");
408 else if (is_char)
409 pp_string (pp, "aliased constant Character");
410 else
411 pp_string (pp, "constant");
413 pp_string (pp, " := ");
414 pp_string (pp, (char *) s);
416 if (is_string)
417 pp_string (pp, " & ASCII.NUL");
419 pp_string (pp, "; -- ");
420 pp_string (pp, sloc.file);
421 pp_character (pp, ':');
422 pp_scalar (pp, "%d", sloc.line);
423 pp_newline (pp);
425 else
427 pp_string (pp, " -- unsupported macro: ");
428 pp_string (pp, (const char *) cpp_macro_definition (parse_in, node));
429 pp_newline (pp);
433 if (num_macros > 0)
434 pp_newline (pp);
437 static const char *source_file;
438 static int max_ada_macros;
440 /* Callback used to count the number of relevant macros from
441 cpp_forall_identifiers. PFILE and V are not used. NODE is the current macro
442 to consider. */
444 static int
445 count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node,
446 void *v ATTRIBUTE_UNUSED)
448 const cpp_macro *macro = node->value.macro;
450 if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
451 && macro->count
452 && *NODE_NAME (node) != '_'
453 && LOCATION_FILE (macro->line) == source_file)
454 max_ada_macros++;
456 return 1;
459 static int store_ada_macro_index;
461 /* Callback used to store relevant macros from cpp_forall_identifiers.
462 PFILE is not used. NODE is the current macro to store if relevant.
463 MACROS is an array of cpp_hashnode* used to store NODE. */
465 static int
466 store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED,
467 cpp_hashnode *node, void *macros)
469 const cpp_macro *macro = node->value.macro;
471 if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
472 && macro->count
473 && *NODE_NAME (node) != '_'
474 && LOCATION_FILE (macro->line) == source_file)
475 ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
477 return 1;
480 /* Callback used to compare (during qsort) macros. NODE1 and NODE2 are the
481 two macro nodes to compare. */
483 static int
484 compare_macro (const void *node1, const void *node2)
486 typedef const cpp_hashnode *const_hnode;
488 const_hnode n1 = *(const const_hnode *) node1;
489 const_hnode n2 = *(const const_hnode *) node2;
491 return n1->value.macro->line - n2->value.macro->line;
494 /* Dump in PP all relevant macros appearing in FILE. */
496 static void
497 dump_ada_macros (pretty_printer *pp, const char* file)
499 cpp_hashnode **macros;
501 /* Initialize file-scope variables. */
502 max_ada_macros = 0;
503 store_ada_macro_index = 0;
504 source_file = file;
506 /* Count all potentially relevant macros, and then sort them by sloc. */
507 cpp_forall_identifiers (parse_in, count_ada_macro, NULL);
508 macros = XALLOCAVEC (cpp_hashnode *, max_ada_macros);
509 cpp_forall_identifiers (parse_in, store_ada_macro, macros);
510 qsort (macros, max_ada_macros, sizeof (cpp_hashnode *), compare_macro);
512 print_ada_macros (pp, macros, max_ada_macros);
515 /* Current source file being handled. */
517 static const char *source_file_base;
519 /* Compare the declaration (DECL) of struct-like types based on the sloc of
520 their last field (if LAST is true), so that more nested types collate before
521 less nested ones.
522 If ORIG_TYPE is true, also consider struct with a DECL_ORIGINAL_TYPE. */
524 static location_t
525 decl_sloc_common (const_tree decl, bool last, bool orig_type)
527 tree type = TREE_TYPE (decl);
529 if (TREE_CODE (decl) == TYPE_DECL
530 && (orig_type || !DECL_ORIGINAL_TYPE (decl))
531 && RECORD_OR_UNION_TYPE_P (type)
532 && TYPE_FIELDS (type))
534 tree f = TYPE_FIELDS (type);
536 if (last)
537 while (TREE_CHAIN (f))
538 f = TREE_CHAIN (f);
540 return DECL_SOURCE_LOCATION (f);
542 else
543 return DECL_SOURCE_LOCATION (decl);
546 /* Return sloc of DECL, using sloc of last field if LAST is true. */
548 location_t
549 decl_sloc (const_tree decl, bool last)
551 return decl_sloc_common (decl, last, false);
554 /* Compare two locations LHS and RHS. */
556 static int
557 compare_location (location_t lhs, location_t rhs)
559 expanded_location xlhs = expand_location (lhs);
560 expanded_location xrhs = expand_location (rhs);
562 if (xlhs.file != xrhs.file)
563 return filename_cmp (xlhs.file, xrhs.file);
565 if (xlhs.line != xrhs.line)
566 return xlhs.line - xrhs.line;
568 if (xlhs.column != xrhs.column)
569 return xlhs.column - xrhs.column;
571 return 0;
574 /* Compare two declarations (LP and RP) by their source location. */
576 static int
577 compare_node (const void *lp, const void *rp)
579 const_tree lhs = *((const tree *) lp);
580 const_tree rhs = *((const tree *) rp);
582 return compare_location (decl_sloc (lhs, true), decl_sloc (rhs, true));
585 /* Compare two comments (LP and RP) by their source location. */
587 static int
588 compare_comment (const void *lp, const void *rp)
590 const cpp_comment *lhs = (const cpp_comment *) lp;
591 const cpp_comment *rhs = (const cpp_comment *) rp;
593 return compare_location (lhs->sloc, rhs->sloc);
596 static tree *to_dump = NULL;
597 static int to_dump_count = 0;
599 /* Collect a list of declarations from T relevant to SOURCE_FILE to be dumped
600 by a subsequent call to dump_ada_nodes. */
602 void
603 collect_ada_nodes (tree t, const char *source_file)
605 tree n;
606 int i = to_dump_count;
608 /* Count the likely relevant nodes. */
609 for (n = t; n; n = TREE_CHAIN (n))
610 if (!DECL_IS_BUILTIN (n)
611 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
612 to_dump_count++;
614 /* Allocate sufficient storage for all nodes. */
615 to_dump = XRESIZEVEC (tree, to_dump, to_dump_count);
617 /* Store the relevant nodes. */
618 for (n = t; n; n = TREE_CHAIN (n))
619 if (!DECL_IS_BUILTIN (n)
620 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
621 to_dump[i++] = n;
624 /* Call back for walk_tree to clear the TREE_VISITED flag of TP. */
626 static tree
627 unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
628 void *data ATTRIBUTE_UNUSED)
630 if (TREE_VISITED (*tp))
631 TREE_VISITED (*tp) = 0;
632 else
633 *walk_subtrees = 0;
635 return NULL_TREE;
638 /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
639 to collect_ada_nodes. CPP_CHECK is used to perform C++ queries on nodes. */
641 static void
642 dump_ada_nodes (pretty_printer *pp, const char *source_file,
643 int (*cpp_check)(tree, cpp_operation))
645 int i, j;
646 cpp_comment_table *comments;
648 /* Sort the table of declarations to dump by sloc. */
649 qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
651 /* Fetch the table of comments. */
652 comments = cpp_get_comments (parse_in);
654 /* Sort the comments table by sloc. */
655 qsort (comments->entries, comments->count, sizeof (cpp_comment),
656 compare_comment);
658 /* Interleave comments and declarations in line number order. */
659 i = j = 0;
662 /* Advance j until comment j is in this file. */
663 while (j != comments->count
664 && LOCATION_FILE (comments->entries[j].sloc) != source_file)
665 j++;
667 /* Advance j until comment j is not a duplicate. */
668 while (j < comments->count - 1
669 && !compare_comment (&comments->entries[j],
670 &comments->entries[j + 1]))
671 j++;
673 /* Write decls until decl i collates after comment j. */
674 while (i != to_dump_count)
676 if (j == comments->count
677 || LOCATION_LINE (decl_sloc (to_dump[i], false))
678 < LOCATION_LINE (comments->entries[j].sloc))
679 print_generic_ada_decl (pp, to_dump[i++], cpp_check, source_file);
680 else
681 break;
684 /* Write comment j, if there is one. */
685 if (j != comments->count)
686 print_comment (pp, comments->entries[j++].comment);
688 } while (i != to_dump_count || j != comments->count);
690 /* Clear the TREE_VISITED flag over each subtree we've dumped. */
691 for (i = 0; i < to_dump_count; i++)
692 walk_tree (&to_dump[i], unmark_visited_r, NULL, NULL);
694 /* Finalize the to_dump table. */
695 if (to_dump)
697 free (to_dump);
698 to_dump = NULL;
699 to_dump_count = 0;
703 /* Print a COMMENT to the output stream PP. */
705 static void
706 print_comment (pretty_printer *pp, const char *comment)
708 int len = strlen (comment);
709 char *str = XALLOCAVEC (char, len + 1);
710 char *tok;
711 bool extra_newline = false;
713 memcpy (str, comment, len + 1);
715 /* Trim C/C++ comment indicators. */
716 if (str[len - 2] == '*' && str[len - 1] == '/')
718 str[len - 2] = ' ';
719 str[len - 1] = '\0';
721 str += 2;
723 tok = strtok (str, "\n");
724 while (tok) {
725 pp_string (pp, " --");
726 pp_string (pp, tok);
727 pp_newline (pp);
728 tok = strtok (NULL, "\n");
730 /* Leave a blank line after multi-line comments. */
731 if (tok)
732 extra_newline = true;
735 if (extra_newline)
736 pp_newline (pp);
739 /* Prints declaration DECL to PP in Ada syntax. The current source file being
740 handled is SOURCE_FILE, and CPP_CHECK is used to perform C++ queries on
741 nodes. */
743 static void
744 print_generic_ada_decl (pretty_printer *pp, tree decl,
745 int (*cpp_check)(tree, cpp_operation),
746 const char* source_file)
748 source_file_base = source_file;
750 if (print_ada_declaration (pp, decl, 0, cpp_check, INDENT_INCR))
752 pp_newline (pp);
753 pp_newline (pp);
757 /* Dump a newline and indent BUFFER by SPC chars. */
759 static void
760 newline_and_indent (pretty_printer *buffer, int spc)
762 pp_newline (buffer);
763 INDENT (spc);
766 struct with { char *s; const char *in_file; int limited; };
767 static struct with *withs = NULL;
768 static int withs_max = 4096;
769 static int with_len = 0;
771 /* Record a "with" clause on package S (a limited with if LIMITED_ACCESS is
772 true), if not already done. */
774 static void
775 append_withs (const char *s, int limited_access)
777 int i;
779 if (withs == NULL)
780 withs = XNEWVEC (struct with, withs_max);
782 if (with_len == withs_max)
784 withs_max *= 2;
785 withs = XRESIZEVEC (struct with, withs, withs_max);
788 for (i = 0; i < with_len; i++)
789 if (!strcmp (s, withs[i].s)
790 && source_file_base == withs[i].in_file)
792 withs[i].limited &= limited_access;
793 return;
796 withs[with_len].s = xstrdup (s);
797 withs[with_len].in_file = source_file_base;
798 withs[with_len].limited = limited_access;
799 with_len++;
802 /* Reset "with" clauses. */
804 static void
805 reset_ada_withs (void)
807 int i;
809 if (!withs)
810 return;
812 for (i = 0; i < with_len; i++)
813 free (withs[i].s);
814 free (withs);
815 withs = NULL;
816 withs_max = 4096;
817 with_len = 0;
820 /* Dump "with" clauses in F. */
822 static void
823 dump_ada_withs (FILE *f)
825 int i;
827 fprintf (f, "with Interfaces.C; use Interfaces.C;\n");
829 for (i = 0; i < with_len; i++)
830 fprintf
831 (f, "%swith %s;\n", withs[i].limited ? "limited " : "", withs[i].s);
834 /* Return suitable Ada package name from FILE. */
836 static char *
837 get_ada_package (const char *file)
839 const char *base;
840 char *res;
841 const char *s;
842 int i;
843 size_t plen;
845 s = strstr (file, "/include/");
846 if (s)
847 base = s + 9;
848 else
849 base = lbasename (file);
851 if (ada_specs_parent == NULL)
852 plen = 0;
853 else
854 plen = strlen (ada_specs_parent) + 1;
856 res = XNEWVEC (char, plen + strlen (base) + 1);
857 if (ada_specs_parent != NULL) {
858 strcpy (res, ada_specs_parent);
859 res[plen - 1] = '.';
862 for (i = plen; *base; base++, i++)
863 switch (*base)
865 case '+':
866 res[i] = 'p';
867 break;
869 case '.':
870 case '-':
871 case '_':
872 case '/':
873 case '\\':
874 res[i] = (i == 0 || res[i - 1] == '.' || res[i - 1] == '_') ? 'u' : '_';
875 break;
877 default:
878 res[i] = *base;
879 break;
881 res[i] = '\0';
883 return res;
886 static const char *ada_reserved[] = {
887 "abort", "abs", "abstract", "accept", "access", "aliased", "all", "and",
888 "array", "at", "begin", "body", "case", "constant", "declare", "delay",
889 "delta", "digits", "do", "else", "elsif", "end", "entry", "exception",
890 "exit", "for", "function", "generic", "goto", "if", "in", "interface", "is",
891 "limited", "loop", "mod", "new", "not", "null", "others", "out", "of", "or",
892 "overriding", "package", "pragma", "private", "procedure", "protected",
893 "raise", "range", "record", "rem", "renames", "requeue", "return", "reverse",
894 "select", "separate", "subtype", "synchronized", "tagged", "task",
895 "terminate", "then", "type", "until", "use", "when", "while", "with", "xor",
896 NULL};
898 /* ??? would be nice to specify this list via a config file, so that users
899 can create their own dictionary of conflicts. */
900 static const char *c_duplicates[] = {
901 /* system will cause troubles with System.Address. */
902 "system",
904 /* The following values have other definitions with same name/other
905 casing. */
906 "funmap",
907 "rl_vi_fWord",
908 "rl_vi_bWord",
909 "rl_vi_eWord",
910 "rl_readline_version",
911 "_Vx_ushort",
912 "USHORT",
913 "XLookupKeysym",
914 NULL};
916 /* Return a declaration tree corresponding to TYPE. */
918 static tree
919 get_underlying_decl (tree type)
921 tree decl = NULL_TREE;
923 if (type == NULL_TREE)
924 return NULL_TREE;
926 /* type is a declaration. */
927 if (DECL_P (type))
928 decl = type;
930 /* type is a typedef. */
931 if (TYPE_P (type) && TYPE_NAME (type) && DECL_P (TYPE_NAME (type)))
932 decl = TYPE_NAME (type);
934 /* TYPE_STUB_DECL has been set for type. */
935 if (TYPE_P (type) && TYPE_STUB_DECL (type) &&
936 DECL_P (TYPE_STUB_DECL (type)))
937 decl = TYPE_STUB_DECL (type);
939 return decl;
942 /* Return whether TYPE has static fields. */
944 static int
945 has_static_fields (const_tree type)
947 tree tmp;
949 for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
951 if (DECL_NAME (tmp) && TREE_STATIC (tmp))
952 return true;
954 return false;
957 /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
958 table). */
960 static int
961 is_tagged_type (const_tree type)
963 tree tmp;
965 if (!type || !RECORD_OR_UNION_TYPE_P (type))
966 return false;
968 for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
969 if (DECL_VINDEX (tmp))
970 return true;
972 return false;
975 /* Generate a legal Ada name from a C NAME, returning a malloc'd string.
976 SPACE_FOUND, if not NULL, is used to indicate whether a space was found in
977 NAME. */
979 static char *
980 to_ada_name (const char *name, int *space_found)
982 const char **names;
983 int len = strlen (name);
984 int j, len2 = 0;
985 int found = false;
986 char *s = XNEWVEC (char, len * 2 + 5);
987 char c;
989 if (space_found)
990 *space_found = false;
992 /* Add trailing "c_" if name is an Ada reserved word. */
993 for (names = ada_reserved; *names; names++)
994 if (!strcasecmp (name, *names))
996 s[len2++] = 'c';
997 s[len2++] = '_';
998 found = true;
999 break;
1002 if (!found)
1003 /* Add trailing "c_" if name is an potential case sensitive duplicate. */
1004 for (names = c_duplicates; *names; names++)
1005 if (!strcmp (name, *names))
1007 s[len2++] = 'c';
1008 s[len2++] = '_';
1009 found = true;
1010 break;
1013 for (j = 0; name[j] == '_'; j++)
1014 s[len2++] = 'u';
1016 if (j > 0)
1017 s[len2++] = '_';
1018 else if (*name == '.' || *name == '$')
1020 s[0] = 'a';
1021 s[1] = 'n';
1022 s[2] = 'o';
1023 s[3] = 'n';
1024 len2 = 4;
1025 j++;
1028 /* Replace unsuitable characters for Ada identifiers. */
1030 for (; j < len; j++)
1031 switch (name[j])
1033 case ' ':
1034 if (space_found)
1035 *space_found = true;
1036 s[len2++] = '_';
1037 break;
1039 /* ??? missing some C++ operators. */
1040 case '=':
1041 s[len2++] = '_';
1043 if (name[j + 1] == '=')
1045 j++;
1046 s[len2++] = 'e';
1047 s[len2++] = 'q';
1049 else
1051 s[len2++] = 'a';
1052 s[len2++] = 's';
1054 break;
1056 case '!':
1057 s[len2++] = '_';
1058 if (name[j + 1] == '=')
1060 j++;
1061 s[len2++] = 'n';
1062 s[len2++] = 'e';
1064 break;
1066 case '~':
1067 s[len2++] = '_';
1068 s[len2++] = 't';
1069 s[len2++] = 'i';
1070 break;
1072 case '&':
1073 case '|':
1074 case '^':
1075 s[len2++] = '_';
1076 s[len2++] = name[j] == '&' ? 'a' : name[j] == '|' ? 'o' : 'x';
1078 if (name[j + 1] == '=')
1080 j++;
1081 s[len2++] = 'e';
1083 break;
1085 case '+':
1086 case '-':
1087 case '*':
1088 case '/':
1089 case '(':
1090 case '[':
1091 if (s[len2 - 1] != '_')
1092 s[len2++] = '_';
1094 switch (name[j + 1]) {
1095 case '\0':
1096 j++;
1097 switch (name[j - 1]) {
1098 case '+': s[len2++] = 'p'; break; /* + */
1099 case '-': s[len2++] = 'm'; break; /* - */
1100 case '*': s[len2++] = 't'; break; /* * */
1101 case '/': s[len2++] = 'd'; break; /* / */
1103 break;
1105 case '=':
1106 j++;
1107 switch (name[j - 1]) {
1108 case '+': s[len2++] = 'p'; break; /* += */
1109 case '-': s[len2++] = 'm'; break; /* -= */
1110 case '*': s[len2++] = 't'; break; /* *= */
1111 case '/': s[len2++] = 'd'; break; /* /= */
1113 s[len2++] = 'a';
1114 break;
1116 case '-': /* -- */
1117 j++;
1118 s[len2++] = 'm';
1119 s[len2++] = 'm';
1120 break;
1122 case '+': /* ++ */
1123 j++;
1124 s[len2++] = 'p';
1125 s[len2++] = 'p';
1126 break;
1128 case ')': /* () */
1129 j++;
1130 s[len2++] = 'o';
1131 s[len2++] = 'p';
1132 break;
1134 case ']': /* [] */
1135 j++;
1136 s[len2++] = 'o';
1137 s[len2++] = 'b';
1138 break;
1141 break;
1143 case '<':
1144 case '>':
1145 c = name[j] == '<' ? 'l' : 'g';
1146 s[len2++] = '_';
1148 switch (name[j + 1]) {
1149 case '\0':
1150 s[len2++] = c;
1151 s[len2++] = 't';
1152 break;
1153 case '=':
1154 j++;
1155 s[len2++] = c;
1156 s[len2++] = 'e';
1157 break;
1158 case '>':
1159 j++;
1160 s[len2++] = 's';
1161 s[len2++] = 'r';
1162 break;
1163 case '<':
1164 j++;
1165 s[len2++] = 's';
1166 s[len2++] = 'l';
1167 break;
1168 default:
1169 break;
1171 break;
1173 case '_':
1174 if (len2 && s[len2 - 1] == '_')
1175 s[len2++] = 'u';
1176 /* fall through */
1178 default:
1179 s[len2++] = name[j];
1182 if (s[len2 - 1] == '_')
1183 s[len2++] = 'u';
1185 s[len2] = '\0';
1187 return s;
1190 /* Return true if DECL refers to a C++ class type for which a
1191 separate enclosing package has been or should be generated. */
1193 static bool
1194 separate_class_package (tree decl)
1196 if (decl)
1198 tree type = TREE_TYPE (decl);
1199 return type
1200 && TREE_CODE (type) == RECORD_TYPE
1201 && (TYPE_METHODS (type) || has_static_fields (type));
1203 else
1204 return false;
1207 static bool package_prefix = true;
1209 /* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
1210 syntax. LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1211 'with' clause rather than a regular 'with' clause. */
1213 static void
1214 pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
1215 int limited_access)
1217 const char *name = IDENTIFIER_POINTER (node);
1218 int space_found = false;
1219 char *s = to_ada_name (name, &space_found);
1220 tree decl;
1222 /* If the entity is a type and comes from another file, generate "package"
1223 prefix. */
1225 decl = get_underlying_decl (type);
1227 if (decl)
1229 expanded_location xloc = expand_location (decl_sloc (decl, false));
1231 if (xloc.file && xloc.line)
1233 if (xloc.file != source_file_base)
1235 switch (TREE_CODE (type))
1237 case ENUMERAL_TYPE:
1238 case INTEGER_TYPE:
1239 case REAL_TYPE:
1240 case FIXED_POINT_TYPE:
1241 case BOOLEAN_TYPE:
1242 case REFERENCE_TYPE:
1243 case POINTER_TYPE:
1244 case ARRAY_TYPE:
1245 case RECORD_TYPE:
1246 case UNION_TYPE:
1247 case QUAL_UNION_TYPE:
1248 case TYPE_DECL:
1250 char *s1 = get_ada_package (xloc.file);
1252 if (package_prefix)
1254 append_withs (s1, limited_access);
1255 pp_string (buffer, s1);
1256 pp_character (buffer, '.');
1258 free (s1);
1260 break;
1261 default:
1262 break;
1265 if (separate_class_package (decl))
1267 pp_string (buffer, "Class_");
1268 pp_string (buffer, s);
1269 pp_string (buffer, ".");
1276 if (space_found)
1277 if (!strcmp (s, "short_int"))
1278 pp_string (buffer, "short");
1279 else if (!strcmp (s, "short_unsigned_int"))
1280 pp_string (buffer, "unsigned_short");
1281 else if (!strcmp (s, "unsigned_int"))
1282 pp_string (buffer, "unsigned");
1283 else if (!strcmp (s, "long_int"))
1284 pp_string (buffer, "long");
1285 else if (!strcmp (s, "long_unsigned_int"))
1286 pp_string (buffer, "unsigned_long");
1287 else if (!strcmp (s, "long_long_int"))
1288 pp_string (buffer, "Long_Long_Integer");
1289 else if (!strcmp (s, "long_long_unsigned_int"))
1291 if (package_prefix)
1293 append_withs ("Interfaces.C.Extensions", false);
1294 pp_string (buffer, "Extensions.unsigned_long_long");
1296 else
1297 pp_string (buffer, "unsigned_long_long");
1299 else
1300 pp_string(buffer, s);
1301 else
1302 if (!strcmp (s, "bool"))
1304 if (package_prefix)
1306 append_withs ("Interfaces.C.Extensions", false);
1307 pp_string (buffer, "Extensions.bool");
1309 else
1310 pp_string (buffer, "bool");
1312 else
1313 pp_string(buffer, s);
1315 free (s);
1318 /* Dump in BUFFER the assembly name of T. */
1320 static void
1321 pp_asm_name (pretty_printer *buffer, tree t)
1323 tree name = DECL_ASSEMBLER_NAME (t);
1324 char *ada_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (name) + 1), *s;
1325 const char *ident = IDENTIFIER_POINTER (name);
1327 for (s = ada_name; *ident; ident++)
1329 if (*ident == ' ')
1330 break;
1331 else if (*ident != '*')
1332 *s++ = *ident;
1335 *s = '\0';
1336 pp_string (buffer, ada_name);
1339 /* Dump in BUFFER the name of a DECL node if set, following Ada syntax.
1340 LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1341 'with' clause rather than a regular 'with' clause. */
1343 static void
1344 dump_ada_decl_name (pretty_printer *buffer, tree decl, int limited_access)
1346 if (DECL_NAME (decl))
1347 pp_ada_tree_identifier (buffer, DECL_NAME (decl), decl, limited_access);
1348 else
1350 tree type_name = TYPE_NAME (TREE_TYPE (decl));
1352 if (!type_name)
1354 pp_string (buffer, "anon");
1355 if (TREE_CODE (decl) == FIELD_DECL)
1356 pp_scalar (buffer, "%d", DECL_UID (decl));
1357 else
1358 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (decl)));
1360 else if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1361 pp_ada_tree_identifier (buffer, type_name, decl, limited_access);
1365 /* Dump in BUFFER a name based on both T1 and T2, followed by S. */
1367 static void
1368 dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2, const char *s)
1370 if (DECL_NAME (t1))
1371 pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, false);
1372 else
1374 pp_string (buffer, "anon");
1375 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t1)));
1378 pp_character (buffer, '_');
1380 if (DECL_NAME (t1))
1381 pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, false);
1382 else
1384 pp_string (buffer, "anon");
1385 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t2)));
1388 pp_string (buffer, s);
1391 /* Dump in BUFFER pragma Import C/CPP on a given node T. */
1393 static void
1394 dump_ada_import (pretty_printer *buffer, tree t)
1396 const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
1397 int is_stdcall = TREE_CODE (t) == FUNCTION_DECL &&
1398 lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (t)));
1400 if (is_stdcall)
1401 pp_string (buffer, "pragma Import (Stdcall, ");
1402 else if (name[0] == '_' && name[1] == 'Z')
1403 pp_string (buffer, "pragma Import (CPP, ");
1404 else
1405 pp_string (buffer, "pragma Import (C, ");
1407 dump_ada_decl_name (buffer, t, false);
1408 pp_string (buffer, ", \"");
1410 if (is_stdcall)
1411 pp_string (buffer, IDENTIFIER_POINTER (DECL_NAME (t)));
1412 else
1413 pp_asm_name (buffer, t);
1415 pp_string (buffer, "\");");
1418 /* Check whether T and its type have different names, and append "the_"
1419 otherwise in BUFFER. */
1421 static void
1422 check_name (pretty_printer *buffer, tree t)
1424 const char *s;
1425 tree tmp = TREE_TYPE (t);
1427 while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp))
1428 tmp = TREE_TYPE (tmp);
1430 if (TREE_CODE (tmp) != FUNCTION_TYPE)
1432 if (TREE_CODE (tmp) == IDENTIFIER_NODE)
1433 s = IDENTIFIER_POINTER (tmp);
1434 else if (!TYPE_NAME (tmp))
1435 s = "";
1436 else if (TREE_CODE (TYPE_NAME (tmp)) == IDENTIFIER_NODE)
1437 s = IDENTIFIER_POINTER (TYPE_NAME (tmp));
1438 else
1439 s = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp)));
1441 if (!strcasecmp (IDENTIFIER_POINTER (DECL_NAME (t)), s))
1442 pp_string (buffer, "the_");
1446 /* Dump in BUFFER a function declaration FUNC with Ada syntax.
1447 IS_METHOD indicates whether FUNC is a C++ method.
1448 IS_CONSTRUCTOR whether FUNC is a C++ constructor.
1449 IS_DESTRUCTOR whether FUNC is a C++ destructor.
1450 SPC is the current indentation level. */
1452 static int
1453 dump_ada_function_declaration (pretty_printer *buffer, tree func,
1454 int is_method, int is_constructor,
1455 int is_destructor, int spc)
1457 tree arg;
1458 const tree node = TREE_TYPE (func);
1459 char buf[16];
1460 int num = 0, num_args = 0, have_args = true, have_ellipsis = false;
1462 /* Compute number of arguments. */
1463 arg = TYPE_ARG_TYPES (node);
1465 if (arg)
1467 while (TREE_CHAIN (arg) && arg != error_mark_node)
1469 num_args++;
1470 arg = TREE_CHAIN (arg);
1473 if (TREE_CODE (TREE_VALUE (arg)) != VOID_TYPE)
1475 num_args++;
1476 have_ellipsis = true;
1480 if (is_constructor)
1481 num_args--;
1483 if (is_destructor)
1484 num_args = 1;
1486 if (num_args > 2)
1487 newline_and_indent (buffer, spc + 1);
1489 if (num_args > 0)
1491 pp_space (buffer);
1492 pp_character (buffer, '(');
1495 if (TREE_CODE (func) == FUNCTION_DECL)
1496 arg = DECL_ARGUMENTS (func);
1497 else
1498 arg = NULL_TREE;
1500 if (arg == NULL_TREE)
1502 have_args = false;
1503 arg = TYPE_ARG_TYPES (node);
1505 if (arg && TREE_CODE (TREE_VALUE (arg)) == VOID_TYPE)
1506 arg = NULL_TREE;
1509 if (is_constructor)
1510 arg = TREE_CHAIN (arg);
1512 /* Print the argument names (if available) & types. */
1514 for (num = 1; num <= num_args; num++)
1516 if (have_args)
1518 if (DECL_NAME (arg))
1520 check_name (buffer, arg);
1521 pp_ada_tree_identifier (buffer, DECL_NAME (arg), 0, false);
1522 pp_string (buffer, " : ");
1524 else
1526 sprintf (buf, "arg%d : ", num);
1527 pp_string (buffer, buf);
1530 dump_generic_ada_node
1531 (buffer, TREE_TYPE (arg), node, NULL, spc, 0, true);
1533 else
1535 sprintf (buf, "arg%d : ", num);
1536 pp_string (buffer, buf);
1537 dump_generic_ada_node
1538 (buffer, TREE_VALUE (arg), node, NULL, spc, 0, true);
1541 if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg))
1542 && is_tagged_type (TREE_TYPE (TREE_TYPE (arg))))
1544 if (!is_method
1545 || (num != 1 || (!DECL_VINDEX (func) && !is_constructor)))
1546 pp_string (buffer, "'Class");
1549 arg = TREE_CHAIN (arg);
1551 if (num < num_args)
1553 pp_character (buffer, ';');
1555 if (num_args > 2)
1556 newline_and_indent (buffer, spc + INDENT_INCR);
1557 else
1558 pp_space (buffer);
1562 if (have_ellipsis)
1564 pp_string (buffer, " -- , ...");
1565 newline_and_indent (buffer, spc + INDENT_INCR);
1568 if (num_args > 0)
1569 pp_character (buffer, ')');
1570 return num_args;
1573 /* Dump in BUFFER all the domains associated with an array NODE,
1574 using Ada syntax. SPC is the current indentation level. */
1576 static void
1577 dump_ada_array_domains (pretty_printer *buffer, tree node, int spc)
1579 int first = 1;
1580 pp_character (buffer, '(');
1582 for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node))
1584 tree domain = TYPE_DOMAIN (node);
1586 if (domain)
1588 tree min = TYPE_MIN_VALUE (domain);
1589 tree max = TYPE_MAX_VALUE (domain);
1591 if (!first)
1592 pp_string (buffer, ", ");
1593 first = 0;
1595 if (min)
1596 dump_generic_ada_node (buffer, min, NULL_TREE, NULL, spc, 0, true);
1597 pp_string (buffer, " .. ");
1599 /* If the upper bound is zero, gcc may generate a NULL_TREE
1600 for TYPE_MAX_VALUE rather than an integer_cst. */
1601 if (max)
1602 dump_generic_ada_node (buffer, max, NULL_TREE, NULL, spc, 0, true);
1603 else
1604 pp_string (buffer, "0");
1606 else
1607 pp_string (buffer, "size_t");
1609 pp_character (buffer, ')');
1612 /* Dump in BUFFER file:line information related to NODE. */
1614 static void
1615 dump_sloc (pretty_printer *buffer, tree node)
1617 expanded_location xloc;
1619 xloc.file = NULL;
1621 if (TREE_CODE_CLASS (TREE_CODE (node)) == tcc_declaration)
1622 xloc = expand_location (DECL_SOURCE_LOCATION (node));
1623 else if (EXPR_HAS_LOCATION (node))
1624 xloc = expand_location (EXPR_LOCATION (node));
1626 if (xloc.file)
1628 pp_string (buffer, xloc.file);
1629 pp_string (buffer, ":");
1630 pp_decimal_int (buffer, xloc.line);
1634 /* Return true if T designates a one dimension array of "char". */
1636 static bool
1637 is_char_array (tree t)
1639 tree tmp;
1640 int num_dim = 0;
1642 /* Retrieve array's type. */
1643 tmp = t;
1644 while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1646 num_dim++;
1647 tmp = TREE_TYPE (tmp);
1650 tmp = TREE_TYPE (tmp);
1651 return num_dim == 1 && TREE_CODE (tmp) == INTEGER_TYPE
1652 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp))), "char");
1655 /* Dump in BUFFER an array type T in Ada syntax. Assume that the "type"
1656 keyword and name have already been printed. SPC is the indentation
1657 level. */
1659 static void
1660 dump_ada_array_type (pretty_printer *buffer, tree t, int spc)
1662 tree tmp;
1663 bool char_array = is_char_array (t);
1665 /* Special case char arrays. */
1666 if (char_array)
1668 pp_string (buffer, "Interfaces.C.char_array ");
1670 else
1671 pp_string (buffer, "array ");
1673 /* Print the dimensions. */
1674 dump_ada_array_domains (buffer, TREE_TYPE (t), spc);
1676 /* Retrieve array's type. */
1677 tmp = TREE_TYPE (t);
1678 while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1679 tmp = TREE_TYPE (tmp);
1681 /* Print array's type. */
1682 if (!char_array)
1684 pp_string (buffer, " of ");
1686 if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE)
1687 pp_string (buffer, "aliased ");
1689 dump_generic_ada_node
1690 (buffer, TREE_TYPE (tmp), TREE_TYPE (t), NULL, spc, false, true);
1694 /* Dump in BUFFER type names associated with a template, each prepended with
1695 '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.
1696 CPP_CHECK is used to perform C++ queries on nodes.
1697 SPC is the indentation level. */
1699 static void
1700 dump_template_types (pretty_printer *buffer, tree types,
1701 int (*cpp_check)(tree, cpp_operation), int spc)
1703 size_t i;
1704 size_t len = TREE_VEC_LENGTH (types);
1706 for (i = 0; i < len; i++)
1708 tree elem = TREE_VEC_ELT (types, i);
1709 pp_character (buffer, '_');
1710 if (!dump_generic_ada_node (buffer, elem, 0, cpp_check, spc, false, true))
1712 pp_string (buffer, "unknown");
1713 pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
1718 /* Dump in BUFFER the contents of all class instantiations associated with
1719 a given template T. CPP_CHECK is used to perform C++ queries on nodes.
1720 SPC is the indentation level. */
1722 static int
1723 dump_ada_template (pretty_printer *buffer, tree t,
1724 int (*cpp_check)(tree, cpp_operation), int spc)
1726 /* DECL_VINDEX is DECL_TEMPLATE_INSTANTIATIONS in this context. */
1727 tree inst = DECL_VINDEX (t);
1728 /* DECL_RESULT_FLD is DECL_TEMPLATE_RESULT in this context. */
1729 tree result = DECL_RESULT_FLD (t);
1730 int num_inst = 0;
1732 /* Don't look at template declarations declaring something coming from
1733 another file. This can occur for template friend declarations. */
1734 if (LOCATION_FILE (decl_sloc (result, false))
1735 != LOCATION_FILE (decl_sloc (t, false)))
1736 return 0;
1738 while (inst && inst != error_mark_node)
1740 tree types = TREE_PURPOSE (inst);
1741 tree instance = TREE_VALUE (inst);
1743 if (TREE_VEC_LENGTH (types) == 0)
1744 break;
1746 if (!TYPE_P (instance) || !TYPE_METHODS (instance))
1747 break;
1749 num_inst++;
1750 INDENT (spc);
1751 pp_string (buffer, "package ");
1752 package_prefix = false;
1753 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1754 dump_template_types (buffer, types, cpp_check, spc);
1755 pp_string (buffer, " is");
1756 spc += INDENT_INCR;
1757 newline_and_indent (buffer, spc);
1759 TREE_VISITED (get_underlying_decl (instance)) = 1;
1760 pp_string (buffer, "type ");
1761 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1762 package_prefix = true;
1764 if (is_tagged_type (instance))
1765 pp_string (buffer, " is tagged limited ");
1766 else
1767 pp_string (buffer, " is limited ");
1769 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, false);
1770 pp_newline (buffer);
1771 spc -= INDENT_INCR;
1772 newline_and_indent (buffer, spc);
1774 pp_string (buffer, "end;");
1775 newline_and_indent (buffer, spc);
1776 pp_string (buffer, "use ");
1777 package_prefix = false;
1778 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1779 dump_template_types (buffer, types, cpp_check, spc);
1780 package_prefix = true;
1781 pp_semicolon (buffer);
1782 pp_newline (buffer);
1783 pp_newline (buffer);
1785 inst = TREE_CHAIN (inst);
1788 return num_inst > 0;
1791 /* Return true if NODE is a simple enum types, that can be mapped to an
1792 Ada enum type directly. */
1794 static bool
1795 is_simple_enum (tree node)
1797 unsigned HOST_WIDE_INT count = 0;
1798 tree value;
1800 for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
1802 tree int_val = TREE_VALUE (value);
1804 if (TREE_CODE (int_val) != INTEGER_CST)
1805 int_val = DECL_INITIAL (int_val);
1807 if (!host_integerp (int_val, 0))
1808 return false;
1809 else if (TREE_INT_CST_LOW (int_val) != count)
1810 return false;
1812 count++;
1815 return true;
1818 static bool in_function = true;
1819 static bool bitfield_used = false;
1821 /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
1822 TYPE. CPP_CHECK is used to perform C++ queries on nodes. SPC is the
1823 indentation level. LIMITED_ACCESS indicates whether NODE can be referenced
1824 via a "limited with" clause. NAME_ONLY indicates whether we should only
1825 dump the name of NODE, instead of its full declaration. */
1827 static int
1828 dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
1829 int (*cpp_check)(tree, cpp_operation), int spc,
1830 int limited_access, bool name_only)
1832 if (node == NULL_TREE)
1833 return 0;
1835 switch (TREE_CODE (node))
1837 case ERROR_MARK:
1838 pp_string (buffer, "<<< error >>>");
1839 return 0;
1841 case IDENTIFIER_NODE:
1842 pp_ada_tree_identifier (buffer, node, type, limited_access);
1843 break;
1845 case TREE_LIST:
1846 pp_string (buffer, "--- unexpected node: TREE_LIST");
1847 return 0;
1849 case TREE_BINFO:
1850 dump_generic_ada_node
1851 (buffer, BINFO_TYPE (node), type, cpp_check,
1852 spc, limited_access, name_only);
1854 case TREE_VEC:
1855 pp_string (buffer, "--- unexpected node: TREE_VEC");
1856 return 0;
1858 case VOID_TYPE:
1859 if (package_prefix)
1861 append_withs ("System", false);
1862 pp_string (buffer, "System.Address");
1864 else
1865 pp_string (buffer, "address");
1866 break;
1868 case VECTOR_TYPE:
1869 pp_string (buffer, "<vector>");
1870 break;
1872 case COMPLEX_TYPE:
1873 pp_string (buffer, "<complex>");
1874 break;
1876 case ENUMERAL_TYPE:
1877 if (name_only)
1878 dump_generic_ada_node
1879 (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true);
1880 else
1882 tree value = TYPE_VALUES (node);
1884 if (is_simple_enum (node))
1886 bool first = true;
1887 spc += INDENT_INCR;
1888 newline_and_indent (buffer, spc - 1);
1889 pp_string (buffer, "(");
1890 for (; value; value = TREE_CHAIN (value))
1892 if (first)
1893 first = false;
1894 else
1896 pp_string (buffer, ",");
1897 newline_and_indent (buffer, spc);
1900 pp_ada_tree_identifier
1901 (buffer, TREE_PURPOSE (value), node, false);
1903 pp_string (buffer, ");");
1904 spc -= INDENT_INCR;
1905 newline_and_indent (buffer, spc);
1906 pp_string (buffer, "pragma Convention (C, ");
1907 dump_generic_ada_node
1908 (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
1909 cpp_check, spc, 0, true);
1910 pp_string (buffer, ")");
1912 else
1914 pp_string (buffer, "unsigned");
1915 for (; value; value = TREE_CHAIN (value))
1917 pp_semicolon (buffer);
1918 newline_and_indent (buffer, spc);
1920 pp_ada_tree_identifier
1921 (buffer, TREE_PURPOSE (value), node, false);
1922 pp_string (buffer, " : constant ");
1924 dump_generic_ada_node
1925 (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
1926 cpp_check, spc, 0, true);
1928 pp_string (buffer, " := ");
1929 dump_generic_ada_node
1930 (buffer,
1931 TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
1932 TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
1933 node, cpp_check, spc, false, true);
1937 break;
1939 case INTEGER_TYPE:
1940 case REAL_TYPE:
1941 case FIXED_POINT_TYPE:
1942 case BOOLEAN_TYPE:
1944 enum tree_code_class tclass;
1946 tclass = TREE_CODE_CLASS (TREE_CODE (node));
1948 if (tclass == tcc_declaration)
1950 if (DECL_NAME (node))
1951 pp_ada_tree_identifier
1952 (buffer, DECL_NAME (node), 0, limited_access);
1953 else
1954 pp_string (buffer, "<unnamed type decl>");
1956 else if (tclass == tcc_type)
1958 if (TYPE_NAME (node))
1960 if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
1961 pp_ada_tree_identifier (buffer, TYPE_NAME (node),
1962 node, limited_access);
1963 else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
1964 && DECL_NAME (TYPE_NAME (node)))
1965 dump_ada_decl_name (buffer, TYPE_NAME (node), limited_access);
1966 else
1967 pp_string (buffer, "<unnamed type>");
1969 else if (TREE_CODE (node) == INTEGER_TYPE)
1971 append_withs ("Interfaces.C.Extensions", false);
1972 bitfield_used = true;
1974 if (TYPE_PRECISION (node) == 1)
1975 pp_string (buffer, "Extensions.Unsigned_1");
1976 else
1978 pp_string (buffer, (TYPE_UNSIGNED (node)
1979 ? "Extensions.Unsigned_"
1980 : "Extensions.Signed_"));
1981 pp_decimal_int (buffer, TYPE_PRECISION (node));
1984 else
1985 pp_string (buffer, "<unnamed type>");
1987 break;
1990 case POINTER_TYPE:
1991 case REFERENCE_TYPE:
1992 if (name_only && TYPE_NAME (node))
1993 dump_generic_ada_node
1994 (buffer, TYPE_NAME (node), node, cpp_check,
1995 spc, limited_access, true);
1997 else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
1999 tree fnode = TREE_TYPE (node);
2000 bool is_function;
2001 bool prev_in_function = in_function;
2003 if (VOID_TYPE_P (TREE_TYPE (fnode)))
2005 is_function = false;
2006 pp_string (buffer, "access procedure");
2008 else
2010 is_function = true;
2011 pp_string (buffer, "access function");
2014 in_function = is_function;
2015 dump_ada_function_declaration
2016 (buffer, node, false, false, false, spc + INDENT_INCR);
2017 in_function = prev_in_function;
2019 if (is_function)
2021 pp_string (buffer, " return ");
2022 dump_generic_ada_node
2023 (buffer, TREE_TYPE (fnode), type, cpp_check, spc, 0, true);
2026 /* If we are dumping the full type, it means we are part of a
2027 type definition and need also a Convention C pragma. */
2028 if (!name_only)
2030 pp_semicolon (buffer);
2031 newline_and_indent (buffer, spc);
2032 pp_string (buffer, "pragma Convention (C, ");
2033 dump_generic_ada_node
2034 (buffer, type, 0, cpp_check, spc, false, true);
2035 pp_string (buffer, ")");
2038 else
2040 int is_access = false;
2041 unsigned int quals = TYPE_QUALS (TREE_TYPE (node));
2043 if (VOID_TYPE_P (TREE_TYPE (node)))
2045 if (!name_only)
2046 pp_string (buffer, "new ");
2047 if (package_prefix)
2049 append_withs ("System", false);
2050 pp_string (buffer, "System.Address");
2052 else
2053 pp_string (buffer, "address");
2055 else
2057 if (TREE_CODE (node) == POINTER_TYPE
2058 && TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE
2059 && !strcmp
2060 (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME
2061 (TREE_TYPE (node)))), "char"))
2063 if (!name_only)
2064 pp_string (buffer, "new ");
2066 if (package_prefix)
2068 pp_string (buffer, "Interfaces.C.Strings.chars_ptr");
2069 append_withs ("Interfaces.C.Strings", false);
2071 else
2072 pp_string (buffer, "chars_ptr");
2074 else
2076 /* For now, handle all access-to-access or
2077 access-to-unknown-structs as opaque system.address. */
2079 tree type_name = TYPE_NAME (TREE_TYPE (node));
2080 const_tree typ2 = !type ||
2081 DECL_P (type) ? type : TYPE_NAME (type);
2082 const_tree underlying_type =
2083 get_underlying_decl (TREE_TYPE (node));
2085 if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE
2086 /* Pointer to pointer. */
2088 || (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2089 && (!underlying_type
2090 || !TYPE_FIELDS (TREE_TYPE (underlying_type))))
2091 /* Pointer to opaque structure. */
2093 || underlying_type == NULL_TREE
2094 || (!typ2
2095 && !TREE_VISITED (underlying_type)
2096 && !TREE_VISITED (type_name)
2097 && !is_tagged_type (TREE_TYPE (node))
2098 && DECL_SOURCE_FILE (underlying_type)
2099 == source_file_base)
2100 || (type_name && typ2
2101 && DECL_P (underlying_type)
2102 && DECL_P (typ2)
2103 && decl_sloc (underlying_type, true)
2104 > decl_sloc (typ2, true)
2105 && DECL_SOURCE_FILE (underlying_type)
2106 == DECL_SOURCE_FILE (typ2)))
2108 if (package_prefix)
2110 append_withs ("System", false);
2111 if (!name_only)
2112 pp_string (buffer, "new ");
2113 pp_string (buffer, "System.Address");
2115 else
2116 pp_string (buffer, "address");
2117 return spc;
2120 if (!package_prefix)
2121 pp_string (buffer, "access");
2122 else if (AGGREGATE_TYPE_P (TREE_TYPE (node)))
2124 if (!type || TREE_CODE (type) != FUNCTION_DECL)
2126 pp_string (buffer, "access ");
2127 is_access = true;
2129 if (quals & TYPE_QUAL_CONST)
2130 pp_string (buffer, "constant ");
2131 else if (!name_only)
2132 pp_string (buffer, "all ");
2134 else if (quals & TYPE_QUAL_CONST)
2135 pp_string (buffer, "in ");
2136 else if (in_function)
2138 is_access = true;
2139 pp_string (buffer, "access ");
2141 else
2143 is_access = true;
2144 pp_string (buffer, "access ");
2145 /* ??? should be configurable: access or in out. */
2148 else
2150 is_access = true;
2151 pp_string (buffer, "access ");
2153 if (!name_only)
2154 pp_string (buffer, "all ");
2157 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2158 && type_name != NULL_TREE)
2159 dump_generic_ada_node
2160 (buffer, type_name,
2161 TREE_TYPE (node), cpp_check, spc, is_access, true);
2162 else
2163 dump_generic_ada_node
2164 (buffer, TREE_TYPE (node), TREE_TYPE (node),
2165 cpp_check, spc, 0, true);
2169 break;
2171 case ARRAY_TYPE:
2172 if (name_only)
2173 dump_generic_ada_node
2174 (buffer, TYPE_NAME (node), node, cpp_check,
2175 spc, limited_access, true);
2176 else
2177 dump_ada_array_type (buffer, node, spc);
2178 break;
2180 case RECORD_TYPE:
2181 case UNION_TYPE:
2182 case QUAL_UNION_TYPE:
2183 if (name_only)
2185 if (TYPE_NAME (node))
2186 dump_generic_ada_node
2187 (buffer, TYPE_NAME (node), node, cpp_check,
2188 spc, limited_access, true);
2189 else
2191 pp_string (buffer, "anon_");
2192 pp_scalar (buffer, "%d", TYPE_UID (node));
2195 else
2196 print_ada_struct_decl
2197 (buffer, node, type, cpp_check, spc, true);
2198 break;
2200 case INTEGER_CST:
2201 /* We treat the upper half of the sizetype range as negative. This
2202 is consistent with the internal treatment and makes it possible
2203 to generate the (0 .. -1) range for flexible array members. */
2204 if (TREE_TYPE (node) == sizetype)
2205 node = fold_convert (ssizetype, node);
2206 if (host_integerp (node, 0))
2207 pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
2208 else if (host_integerp (node, 1))
2209 pp_unsigned_wide_integer (buffer, TREE_INT_CST_LOW (node));
2210 else
2212 tree val = node;
2213 unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (val);
2214 HOST_WIDE_INT high = TREE_INT_CST_HIGH (val);
2216 if (tree_int_cst_sgn (val) < 0)
2218 pp_character (buffer, '-');
2219 high = ~high + !low;
2220 low = -low;
2222 sprintf (pp_buffer (buffer)->digit_buffer,
2223 ADA_HOST_WIDE_INT_PRINT_DOUBLE_HEX,
2224 (unsigned HOST_WIDE_INT) high, low);
2225 pp_string (buffer, pp_buffer (buffer)->digit_buffer);
2227 break;
2229 case REAL_CST:
2230 case FIXED_CST:
2231 case COMPLEX_CST:
2232 case STRING_CST:
2233 case VECTOR_CST:
2234 return 0;
2236 case FUNCTION_DECL:
2237 case CONST_DECL:
2238 dump_ada_decl_name (buffer, node, limited_access);
2239 break;
2241 case TYPE_DECL:
2242 if (DECL_IS_BUILTIN (node))
2244 /* Don't print the declaration of built-in types. */
2246 if (name_only)
2248 /* If we're in the middle of a declaration, defaults to
2249 System.Address. */
2250 if (package_prefix)
2252 append_withs ("System", false);
2253 pp_string (buffer, "System.Address");
2255 else
2256 pp_string (buffer, "address");
2258 break;
2261 if (name_only)
2262 dump_ada_decl_name (buffer, node, limited_access);
2263 else
2265 if (is_tagged_type (TREE_TYPE (node)))
2267 tree tmp = TYPE_FIELDS (TREE_TYPE (node));
2268 int first = 1;
2270 /* Look for ancestors. */
2271 for (; tmp; tmp = TREE_CHAIN (tmp))
2273 if (!DECL_NAME (tmp) && is_tagged_type (TREE_TYPE (tmp)))
2275 if (first)
2277 pp_string (buffer, "limited new ");
2278 first = 0;
2280 else
2281 pp_string (buffer, " and ");
2283 dump_ada_decl_name
2284 (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
2288 pp_string (buffer, first ? "tagged limited " : " with ");
2290 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2291 && TYPE_METHODS (TREE_TYPE (node)))
2292 pp_string (buffer, "limited ");
2294 dump_generic_ada_node
2295 (buffer, TREE_TYPE (node), type, cpp_check, spc, false, false);
2297 break;
2299 case VAR_DECL:
2300 case PARM_DECL:
2301 case FIELD_DECL:
2302 case NAMESPACE_DECL:
2303 dump_ada_decl_name (buffer, node, false);
2304 break;
2306 default:
2307 /* Ignore other nodes (e.g. expressions). */
2308 return 0;
2311 return 1;
2314 /* Dump in BUFFER NODE's methods. CPP_CHECK is used to perform C++ queries on
2315 nodes. SPC is the indentation level. */
2317 static void
2318 print_ada_methods (pretty_printer *buffer, tree node,
2319 int (*cpp_check)(tree, cpp_operation), int spc)
2321 tree tmp = TYPE_METHODS (node);
2322 int res = 1;
2324 if (tmp)
2326 pp_semicolon (buffer);
2328 for (; tmp; tmp = TREE_CHAIN (tmp))
2330 if (res)
2332 pp_newline (buffer);
2333 pp_newline (buffer);
2335 res = print_ada_declaration (buffer, tmp, node, cpp_check, spc);
2340 /* Dump in BUFFER anonymous types nested inside T's definition.
2341 PARENT is the parent node of T.
2342 FORWARD indicates whether a forward declaration of T should be generated.
2343 CPP_CHECK is used to perform C++ queries on
2344 nodes. SPC is the indentation level. */
2346 static void
2347 dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
2348 int (*cpp_check)(tree, cpp_operation), int spc)
2350 tree field, outer, decl;
2352 /* Avoid recursing over the same tree. */
2353 if (TREE_VISITED (t))
2354 return;
2356 /* Find possible anonymous arrays/unions/structs recursively. */
2358 outer = TREE_TYPE (t);
2360 if (outer == NULL_TREE)
2361 return;
2363 if (forward)
2365 pp_string (buffer, "type ");
2366 dump_generic_ada_node
2367 (buffer, t, t, cpp_check, spc, false, true);
2368 pp_semicolon (buffer);
2369 newline_and_indent (buffer, spc);
2370 TREE_VISITED (t) = 1;
2373 field = TYPE_FIELDS (outer);
2374 while (field)
2376 if ((TREE_TYPE (field) != outer
2377 || (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2378 && TREE_TYPE (TREE_TYPE (field)) != outer))
2379 && (!TYPE_NAME (TREE_TYPE (field))
2380 || (TREE_CODE (field) == TYPE_DECL
2381 && DECL_NAME (field) != DECL_NAME (t)
2382 && TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (outer))))
2384 switch (TREE_CODE (TREE_TYPE (field)))
2386 case POINTER_TYPE:
2387 decl = TREE_TYPE (TREE_TYPE (field));
2389 if (TREE_CODE (decl) == FUNCTION_TYPE)
2390 for (decl = TREE_TYPE (decl);
2391 decl && TREE_CODE (decl) == POINTER_TYPE;
2392 decl = TREE_TYPE (decl))
2395 decl = get_underlying_decl (decl);
2397 if (decl
2398 && DECL_P (decl)
2399 && decl_sloc (decl, true) > decl_sloc (t, true)
2400 && DECL_SOURCE_FILE (decl) == DECL_SOURCE_FILE (t)
2401 && !TREE_VISITED (decl)
2402 && !DECL_IS_BUILTIN (decl)
2403 && (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
2404 || TYPE_FIELDS (TREE_TYPE (decl))))
2406 /* Generate forward declaration. */
2408 pp_string (buffer, "type ");
2409 dump_generic_ada_node
2410 (buffer, decl, 0, cpp_check, spc, false, true);
2411 pp_semicolon (buffer);
2412 newline_and_indent (buffer, spc);
2414 /* Ensure we do not generate duplicate forward
2415 declarations for this type. */
2416 TREE_VISITED (decl) = 1;
2418 break;
2420 case ARRAY_TYPE:
2421 /* Special case char arrays. */
2422 if (is_char_array (field))
2423 pp_string (buffer, "sub");
2425 pp_string (buffer, "type ");
2426 dump_ada_double_name (buffer, parent, field, "_array is ");
2427 dump_ada_array_type (buffer, field, spc);
2428 pp_semicolon (buffer);
2429 newline_and_indent (buffer, spc);
2430 break;
2432 case UNION_TYPE:
2433 TREE_VISITED (t) = 1;
2434 dump_nested_types (buffer, field, t, false, cpp_check, spc);
2436 pp_string (buffer, "type ");
2438 if (TYPE_NAME (TREE_TYPE (field)))
2440 dump_generic_ada_node
2441 (buffer, TYPE_NAME (TREE_TYPE (field)), 0, cpp_check,
2442 spc, false, true);
2443 pp_string (buffer, " (discr : unsigned := 0) is ");
2444 print_ada_struct_decl
2445 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2447 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2448 dump_generic_ada_node
2449 (buffer, TREE_TYPE (field), 0, cpp_check,
2450 spc, false, true);
2451 pp_string (buffer, ");");
2452 newline_and_indent (buffer, spc);
2454 pp_string (buffer, "pragma Unchecked_Union (");
2455 dump_generic_ada_node
2456 (buffer, TREE_TYPE (field), 0, cpp_check,
2457 spc, false, true);
2458 pp_string (buffer, ");");
2460 else
2462 dump_ada_double_name
2463 (buffer, parent, field,
2464 "_union (discr : unsigned := 0) is ");
2465 print_ada_struct_decl
2466 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2467 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2468 dump_ada_double_name (buffer, parent, field, "_union);");
2469 newline_and_indent (buffer, spc);
2471 pp_string (buffer, "pragma Unchecked_Union (");
2472 dump_ada_double_name (buffer, parent, field, "_union);");
2475 newline_and_indent (buffer, spc);
2476 break;
2478 case RECORD_TYPE:
2479 if (TYPE_NAME (TREE_TYPE (t)) && !TREE_VISITED (t))
2481 pp_string (buffer, "type ");
2482 dump_generic_ada_node
2483 (buffer, t, parent, 0, spc, false, true);
2484 pp_semicolon (buffer);
2485 newline_and_indent (buffer, spc);
2488 TREE_VISITED (t) = 1;
2489 dump_nested_types (buffer, field, t, false, cpp_check, spc);
2490 pp_string (buffer, "type ");
2492 if (TYPE_NAME (TREE_TYPE (field)))
2494 dump_generic_ada_node
2495 (buffer, TREE_TYPE (field), 0, cpp_check,
2496 spc, false, true);
2497 pp_string (buffer, " is ");
2498 print_ada_struct_decl
2499 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2500 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2501 dump_generic_ada_node
2502 (buffer, TREE_TYPE (field), 0, cpp_check,
2503 spc, false, true);
2504 pp_string (buffer, ");");
2506 else
2508 dump_ada_double_name
2509 (buffer, parent, field, "_struct is ");
2510 print_ada_struct_decl
2511 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2512 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2513 dump_ada_double_name (buffer, parent, field, "_struct);");
2516 newline_and_indent (buffer, spc);
2517 break;
2519 default:
2520 break;
2523 field = TREE_CHAIN (field);
2526 TREE_VISITED (t) = 1;
2529 /* Dump in BUFFER destructor spec corresponding to T. */
2531 static void
2532 print_destructor (pretty_printer *buffer, tree t)
2534 const char *s = IDENTIFIER_POINTER (DECL_NAME (t));
2536 if (*s == '_')
2537 for (s += 2; *s != ' '; s++)
2538 pp_character (buffer, *s);
2539 else
2541 pp_string (buffer, "Delete_");
2542 pp_ada_tree_identifier (buffer, DECL_NAME (t), t, false);
2546 /* Return the name of type T. */
2548 static const char *
2549 type_name (tree t)
2551 tree n = TYPE_NAME (t);
2553 if (TREE_CODE (n) == IDENTIFIER_NODE)
2554 return IDENTIFIER_POINTER (n);
2555 else
2556 return IDENTIFIER_POINTER (DECL_NAME (n));
2559 /* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
2560 CPP_CHECK is used to perform C++ queries on nodes. SPC is the indentation
2561 level. Return 1 if a declaration was printed, 0 otherwise. */
2563 static int
2564 print_ada_declaration (pretty_printer *buffer, tree t, tree type,
2565 int (*cpp_check)(tree, cpp_operation), int spc)
2567 int is_var = 0, need_indent = 0;
2568 int is_class = false;
2569 tree name = TYPE_NAME (TREE_TYPE (t));
2570 tree decl_name = DECL_NAME (t);
2571 tree orig = NULL_TREE;
2573 if (cpp_check && cpp_check (t, IS_TEMPLATE))
2574 return dump_ada_template (buffer, t, cpp_check, spc);
2576 if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
2577 /* Skip enumeral values: will be handled as part of the type itself. */
2578 return 0;
2580 if (TREE_CODE (t) == TYPE_DECL)
2582 orig = DECL_ORIGINAL_TYPE (t);
2584 if (orig && TYPE_STUB_DECL (orig))
2586 tree stub = TYPE_STUB_DECL (orig);
2587 tree typ = TREE_TYPE (stub);
2589 if (TYPE_NAME (typ))
2591 /* If types have same representation, and same name (ignoring
2592 casing), then ignore the second type. */
2593 if (type_name (typ) == type_name (TREE_TYPE (t))
2594 || !strcasecmp (type_name (typ), type_name (TREE_TYPE (t))))
2595 return 0;
2597 INDENT (spc);
2599 if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
2601 pp_string (buffer, "-- skipped empty struct ");
2602 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2604 else
2606 if (!TREE_VISITED (stub)
2607 && DECL_SOURCE_FILE (stub) == source_file_base)
2608 dump_nested_types
2609 (buffer, stub, stub, true, cpp_check, spc);
2611 pp_string (buffer, "subtype ");
2612 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2613 pp_string (buffer, " is ");
2614 dump_generic_ada_node
2615 (buffer, typ, type, 0, spc, false, true);
2616 pp_semicolon (buffer);
2618 return 1;
2622 /* Skip unnamed or anonymous structs/unions/enum types. */
2623 if (!orig && !decl_name && !name)
2625 tree tmp;
2626 location_t sloc;
2628 if (cpp_check || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
2629 return 0;
2631 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
2633 /* Search next items until finding a named type decl. */
2634 sloc = decl_sloc_common (t, true, true);
2636 for (tmp = TREE_CHAIN (t); tmp; tmp = TREE_CHAIN (tmp))
2638 if (TREE_CODE (tmp) == TYPE_DECL
2639 && (DECL_NAME (tmp) || TYPE_NAME (TREE_TYPE (tmp))))
2641 /* If same sloc, it means we can ignore the anonymous
2642 struct. */
2643 if (decl_sloc_common (tmp, true, true) == sloc)
2644 return 0;
2645 else
2646 break;
2649 if (tmp == NULL)
2650 return 0;
2654 if (!orig
2655 && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE
2656 && decl_name
2657 && (*IDENTIFIER_POINTER (decl_name) == '.'
2658 || *IDENTIFIER_POINTER (decl_name) == '$'))
2659 /* Skip anonymous enum types (duplicates of real types). */
2660 return 0;
2662 INDENT (spc);
2664 switch (TREE_CODE (TREE_TYPE (t)))
2666 case RECORD_TYPE:
2667 case UNION_TYPE:
2668 case QUAL_UNION_TYPE:
2669 /* Skip empty structs (typically forward references to real
2670 structs). */
2671 if (!TYPE_FIELDS (TREE_TYPE (t)))
2673 pp_string (buffer, "-- skipped empty struct ");
2674 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2675 return 1;
2678 if (decl_name
2679 && (*IDENTIFIER_POINTER (decl_name) == '.'
2680 || *IDENTIFIER_POINTER (decl_name) == '$'))
2682 pp_string (buffer, "-- skipped anonymous struct ");
2683 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2684 TREE_VISITED (t) = 1;
2685 return 1;
2688 if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2689 pp_string (buffer, "subtype ");
2690 else
2692 dump_nested_types (buffer, t, t, false, cpp_check, spc);
2694 if (separate_class_package (t))
2696 is_class = true;
2697 pp_string (buffer, "package Class_");
2698 dump_generic_ada_node
2699 (buffer, t, type, 0, spc, false, true);
2700 pp_string (buffer, " is");
2701 spc += INDENT_INCR;
2702 newline_and_indent (buffer, spc);
2705 pp_string (buffer, "type ");
2707 break;
2709 case ARRAY_TYPE:
2710 case POINTER_TYPE:
2711 case REFERENCE_TYPE:
2712 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2713 || is_char_array (t))
2714 pp_string (buffer, "subtype ");
2715 else
2716 pp_string (buffer, "type ");
2717 break;
2719 case FUNCTION_TYPE:
2720 pp_string (buffer, "-- skipped function type ");
2721 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2722 return 1;
2723 break;
2725 case ENUMERAL_TYPE:
2726 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2727 || !is_simple_enum (TREE_TYPE (t)))
2728 pp_string (buffer, "subtype ");
2729 else
2730 pp_string (buffer, "type ");
2731 break;
2733 default:
2734 pp_string (buffer, "subtype ");
2736 TREE_VISITED (t) = 1;
2738 else
2740 if (TREE_CODE (t) == VAR_DECL
2741 && decl_name
2742 && *IDENTIFIER_POINTER (decl_name) == '_')
2743 return 0;
2745 need_indent = 1;
2748 /* Print the type and name. */
2749 if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
2751 if (need_indent)
2752 INDENT (spc);
2754 /* Print variable's name. */
2755 dump_generic_ada_node (buffer, t, type, cpp_check, spc, false, true);
2757 if (TREE_CODE (t) == TYPE_DECL)
2759 pp_string (buffer, " is ");
2761 if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2762 dump_generic_ada_node
2763 (buffer, TYPE_NAME (orig), type,
2764 cpp_check, spc, false, true);
2765 else
2766 dump_ada_array_type (buffer, t, spc);
2768 else
2770 tree tmp = TYPE_NAME (TREE_TYPE (t));
2772 if (spc == INDENT_INCR || TREE_STATIC (t))
2773 is_var = 1;
2775 pp_string (buffer, " : ");
2777 if (tmp)
2779 if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE
2780 && TREE_CODE (tmp) != INTEGER_TYPE)
2781 pp_string (buffer, "aliased ");
2783 dump_generic_ada_node (buffer, tmp, type, 0, spc, false, true);
2785 else
2787 pp_string (buffer, "aliased ");
2789 if (!type)
2790 dump_ada_array_type (buffer, t, spc);
2791 else
2792 dump_ada_double_name (buffer, type, t, "_array");
2796 else if (TREE_CODE (t) == FUNCTION_DECL)
2798 bool is_function = true, is_method, is_abstract_class = false;
2799 tree decl_name = DECL_NAME (t);
2800 int prev_in_function = in_function;
2801 bool is_abstract = false;
2802 bool is_constructor = false;
2803 bool is_destructor = false;
2804 bool is_copy_constructor = false;
2806 if (!decl_name)
2807 return 0;
2809 if (cpp_check)
2811 is_abstract = cpp_check (t, IS_ABSTRACT);
2812 is_constructor = cpp_check (t, IS_CONSTRUCTOR);
2813 is_destructor = cpp_check (t, IS_DESTRUCTOR);
2814 is_copy_constructor = cpp_check (t, IS_COPY_CONSTRUCTOR);
2817 /* Skip __comp_dtor destructor which is redundant with the '~class()'
2818 destructor. */
2819 if (is_destructor
2820 && !strncmp (IDENTIFIER_POINTER (decl_name), "__comp", 6))
2821 return 0;
2823 /* Skip copy constructors: some are internal only, and those that are
2824 not cannot be called easily from Ada anyway. */
2825 if (is_copy_constructor)
2826 return 0;
2828 /* If this function has an entry in the dispatch table, we cannot
2829 omit it. */
2830 if (!DECL_VINDEX (t) && *IDENTIFIER_POINTER (decl_name) == '_')
2832 if (IDENTIFIER_POINTER (decl_name)[1] == '_')
2833 return 0;
2835 INDENT (spc);
2836 pp_string (buffer, "-- skipped func ");
2837 pp_string (buffer, IDENTIFIER_POINTER (decl_name));
2838 return 1;
2841 if (need_indent)
2842 INDENT (spc);
2844 if (is_constructor)
2845 pp_string (buffer, "function New_");
2846 else if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
2848 is_function = false;
2849 pp_string (buffer, "procedure ");
2851 else
2852 pp_string (buffer, "function ");
2854 in_function = is_function;
2855 is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
2857 if (is_destructor)
2858 print_destructor (buffer, t);
2859 else
2860 dump_ada_decl_name (buffer, t, false);
2862 dump_ada_function_declaration
2863 (buffer, t, is_method, is_constructor, is_destructor, spc);
2864 in_function = prev_in_function;
2866 if (is_function)
2868 pp_string (buffer, " return ");
2870 if (is_constructor)
2872 dump_ada_decl_name (buffer, t, false);
2874 else
2876 dump_generic_ada_node
2877 (buffer, TREE_TYPE (TREE_TYPE (t)), type, cpp_check,
2878 spc, false, true);
2882 if (is_constructor && cpp_check && type
2883 && AGGREGATE_TYPE_P (type)
2884 && TYPE_METHODS (type))
2886 tree tmp = TYPE_METHODS (type);
2888 for (; tmp; tmp = TREE_CHAIN (tmp))
2889 if (cpp_check (tmp, IS_ABSTRACT))
2891 is_abstract_class = 1;
2892 break;
2896 if (is_abstract || is_abstract_class)
2897 pp_string (buffer, " is abstract");
2899 pp_semicolon (buffer);
2900 pp_string (buffer, " -- ");
2901 dump_sloc (buffer, t);
2903 if (is_abstract)
2904 return 1;
2906 newline_and_indent (buffer, spc);
2908 if (is_constructor)
2910 pp_string (buffer, "pragma CPP_Constructor (New_");
2911 dump_ada_decl_name (buffer, t, false);
2912 pp_string (buffer, ", \"");
2913 pp_asm_name (buffer, t);
2914 pp_string (buffer, "\");");
2916 else if (is_destructor)
2918 pp_string (buffer, "pragma Import (CPP, ");
2919 print_destructor (buffer, t);
2920 pp_string (buffer, ", \"");
2921 pp_asm_name (buffer, t);
2922 pp_string (buffer, "\");");
2924 else
2926 dump_ada_import (buffer, t);
2929 return 1;
2931 else if (TREE_CODE (t) == TYPE_DECL && !DECL_ORIGINAL_TYPE (t))
2933 int is_interface = 0;
2934 int is_abstract_record = 0;
2936 if (need_indent)
2937 INDENT (spc);
2939 /* Anonymous structs/unions */
2940 dump_generic_ada_node
2941 (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
2943 if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
2944 || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE)
2946 pp_string (buffer, " (discr : unsigned := 0)");
2949 pp_string (buffer, " is ");
2951 /* Check whether we have an Ada interface compatible class. */
2952 if (cpp_check && AGGREGATE_TYPE_P (TREE_TYPE (t))
2953 && TYPE_METHODS (TREE_TYPE (t)))
2955 int num_fields = 0;
2956 tree tmp = TYPE_FIELDS (TREE_TYPE (t));
2958 /* Check that there are no fields other than the virtual table. */
2959 for (; tmp; tmp = TREE_CHAIN (tmp))
2961 if (TREE_CODE (tmp) == TYPE_DECL)
2962 continue;
2963 num_fields++;
2966 if (num_fields == 1)
2967 is_interface = 1;
2969 /* Also check that there are only virtual methods. */
2970 for (tmp = TYPE_METHODS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
2972 if (cpp_check (tmp, IS_ABSTRACT))
2973 is_abstract_record = 1;
2974 else
2975 is_interface = 0;
2979 TREE_VISITED (t) = 1;
2980 if (is_interface)
2982 pp_string (buffer, "limited interface; -- ");
2983 dump_sloc (buffer, t);
2984 newline_and_indent (buffer, spc);
2985 pp_string (buffer, "pragma Import (CPP, ");
2986 dump_generic_ada_node
2987 (buffer, TYPE_NAME (TREE_TYPE (t)), type, cpp_check,
2988 spc, false, true);
2989 pp_character (buffer, ')');
2991 print_ada_methods (buffer, TREE_TYPE (t), cpp_check, spc);
2993 else
2995 if (is_abstract_record)
2996 pp_string (buffer, "abstract ");
2997 dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, false);
3000 else
3002 if (need_indent)
3003 INDENT (spc);
3005 if (TREE_CODE (t) == FIELD_DECL && DECL_NAME (t))
3006 check_name (buffer, t);
3008 /* Print variable/type's name. */
3009 dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, true);
3011 if (TREE_CODE (t) == TYPE_DECL)
3013 tree orig = DECL_ORIGINAL_TYPE (t);
3014 int is_subtype = orig && TYPE_NAME (orig) && orig != TREE_TYPE (t);
3016 if (!is_subtype
3017 && (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
3018 || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE))
3019 pp_string (buffer, " (discr : unsigned := 0)");
3021 pp_string (buffer, " is ");
3023 dump_generic_ada_node
3024 (buffer, orig, t, cpp_check, spc, false, is_subtype);
3026 else
3028 if (spc == INDENT_INCR || TREE_STATIC (t))
3029 is_var = 1;
3031 pp_string (buffer, " : ");
3033 /* Print type declaration. */
3035 if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
3036 && !TYPE_NAME (TREE_TYPE (t)))
3038 dump_ada_double_name (buffer, type, t, "_union");
3040 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
3042 if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
3043 pp_string (buffer, "aliased ");
3045 dump_generic_ada_node
3046 (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
3048 else
3050 if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
3051 && (TYPE_NAME (TREE_TYPE (t))
3052 || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE))
3053 pp_string (buffer, "aliased ");
3055 dump_generic_ada_node
3056 (buffer, TREE_TYPE (t), TREE_TYPE (t), cpp_check,
3057 spc, false, true);
3062 if (is_class)
3064 spc -= 3;
3065 newline_and_indent (buffer, spc);
3066 pp_string (buffer, "end;");
3067 newline_and_indent (buffer, spc);
3068 pp_string (buffer, "use Class_");
3069 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
3070 pp_semicolon (buffer);
3071 pp_newline (buffer);
3073 /* All needed indentation/newline performed already, so return 0. */
3074 return 0;
3076 else
3078 pp_string (buffer, "; -- ");
3079 dump_sloc (buffer, t);
3082 if (is_var)
3084 newline_and_indent (buffer, spc);
3085 dump_ada_import (buffer, t);
3088 return 1;
3091 /* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
3092 with Ada syntax. CPP_CHECK is used to perform C++ queries on nodes. SPC
3093 is the indentation level. If DISPLAY_CONVENTION is true, also print the
3094 pragma Convention for NODE. */
3096 static void
3097 print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
3098 int (*cpp_check)(tree, cpp_operation), int spc,
3099 bool display_convention)
3101 tree tmp;
3102 int is_union =
3103 TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
3104 char buf[32];
3105 int field_num = 0;
3106 int field_spc = spc + INDENT_INCR;
3107 int need_semicolon;
3109 bitfield_used = false;
3111 if (!TYPE_FIELDS (node))
3112 pp_string (buffer, "null record;");
3113 else
3115 pp_string (buffer, "record");
3117 /* Print the contents of the structure. */
3119 if (is_union)
3121 newline_and_indent (buffer, spc + INDENT_INCR);
3122 pp_string (buffer, "case discr is");
3123 field_spc = spc + INDENT_INCR * 3;
3126 pp_newline (buffer);
3128 /* Print the non-static fields of the structure. */
3129 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3131 /* Add parent field if needed. */
3132 if (!DECL_NAME (tmp))
3134 if (!is_tagged_type (TREE_TYPE (tmp)))
3136 if (!TYPE_NAME (TREE_TYPE (tmp)))
3137 print_ada_declaration
3138 (buffer, tmp, type, cpp_check, field_spc);
3139 else
3141 INDENT (field_spc);
3143 if (field_num == 0)
3144 pp_string (buffer, "parent : aliased ");
3145 else
3147 sprintf (buf, "field_%d : aliased ", field_num + 1);
3148 pp_string (buffer, buf);
3150 dump_ada_decl_name
3151 (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
3152 pp_semicolon (buffer);
3154 pp_newline (buffer);
3155 field_num++;
3158 /* Avoid printing the structure recursively. */
3159 else if ((TREE_TYPE (tmp) != node
3160 || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
3161 && TREE_TYPE (TREE_TYPE (tmp)) != node))
3162 && TREE_CODE (tmp) != TYPE_DECL
3163 && !TREE_STATIC (tmp))
3165 /* Skip internal virtual table field. */
3166 if (strncmp (IDENTIFIER_POINTER (DECL_NAME (tmp)), "_vptr", 5))
3168 if (is_union)
3170 if (TREE_CHAIN (tmp)
3171 && TREE_TYPE (TREE_CHAIN (tmp)) != node
3172 && TREE_CODE (TREE_CHAIN (tmp)) != TYPE_DECL)
3173 sprintf (buf, "when %d =>", field_num);
3174 else
3175 sprintf (buf, "when others =>");
3177 INDENT (spc + INDENT_INCR * 2);
3178 pp_string (buffer, buf);
3179 pp_newline (buffer);
3182 if (print_ada_declaration (buffer,
3183 tmp, type, cpp_check, field_spc))
3185 pp_newline (buffer);
3186 field_num++;
3192 if (is_union)
3194 INDENT (spc + INDENT_INCR);
3195 pp_string (buffer, "end case;");
3196 pp_newline (buffer);
3199 if (field_num == 0)
3201 INDENT (spc + INDENT_INCR);
3202 pp_string (buffer, "null;");
3203 pp_newline (buffer);
3206 INDENT (spc);
3207 pp_string (buffer, "end record;");
3210 newline_and_indent (buffer, spc);
3212 if (!display_convention)
3213 return;
3215 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
3217 if (TYPE_METHODS (TREE_TYPE (type)))
3218 pp_string (buffer, "pragma Import (CPP, ");
3219 else
3220 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
3222 else
3223 pp_string (buffer, "pragma Convention (C, ");
3225 package_prefix = false;
3226 dump_generic_ada_node
3227 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3228 package_prefix = true;
3229 pp_character (buffer, ')');
3231 if (is_union)
3233 pp_semicolon (buffer);
3234 newline_and_indent (buffer, spc);
3235 pp_string (buffer, "pragma Unchecked_Union (");
3237 dump_generic_ada_node
3238 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3239 pp_character (buffer, ')');
3242 if (bitfield_used)
3244 pp_semicolon (buffer);
3245 newline_and_indent (buffer, spc);
3246 pp_string (buffer, "pragma Pack (");
3247 dump_generic_ada_node
3248 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3249 pp_character (buffer, ')');
3250 bitfield_used = false;
3253 print_ada_methods (buffer, node, cpp_check, spc);
3255 /* Print the static fields of the structure, if any. */
3256 need_semicolon = TYPE_METHODS (node) == NULL_TREE;
3257 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3259 if (DECL_NAME (tmp) && TREE_STATIC (tmp))
3261 if (need_semicolon)
3263 need_semicolon = false;
3264 pp_semicolon (buffer);
3266 pp_newline (buffer);
3267 pp_newline (buffer);
3268 print_ada_declaration (buffer, tmp, type, cpp_check, spc);
3273 /* Dump all the declarations in SOURCE_FILE to an Ada spec.
3274 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3275 nodes for SOURCE_FILE. CPP_CHECK is used to perform C++ queries on
3276 nodes. */
3278 static void
3279 dump_ads (const char *source_file,
3280 void (*collect_all_refs)(const char *),
3281 int (*cpp_check)(tree, cpp_operation))
3283 char *ads_name;
3284 char *pkg_name;
3285 char *s;
3286 FILE *f;
3288 pkg_name = get_ada_package (source_file);
3290 /* Construct the .ads filename and package name. */
3291 ads_name = xstrdup (pkg_name);
3293 for (s = ads_name; *s; s++)
3294 if (*s == '.')
3295 *s = '-';
3296 else
3297 *s = TOLOWER (*s);
3299 ads_name = reconcat (ads_name, ads_name, ".ads", NULL);
3301 /* Write out the .ads file. */
3302 f = fopen (ads_name, "w");
3303 if (f)
3305 pretty_printer pp;
3307 pp_construct (&pp, NULL, 0);
3308 pp_needs_newline (&pp) = true;
3309 pp.buffer->stream = f;
3311 /* Dump all relevant macros. */
3312 dump_ada_macros (&pp, source_file);
3314 /* Reset the table of withs for this file. */
3315 reset_ada_withs ();
3317 (*collect_all_refs) (source_file);
3319 /* Dump all references. */
3320 dump_ada_nodes (&pp, source_file, cpp_check);
3322 /* Requires Ada 2005 syntax, so generate corresponding pragma.
3323 Also, disable style checks since this file is auto-generated. */
3324 fprintf (f, "pragma Ada_2005;\npragma Style_Checks (Off);\n\n");
3326 /* Dump withs. */
3327 dump_ada_withs (f);
3329 fprintf (f, "\npackage %s is\n\n", pkg_name);
3330 pp_write_text_to_stream (&pp);
3331 /* ??? need to free pp */
3332 fprintf (f, "end %s;\n", pkg_name);
3333 fclose (f);
3336 free (ads_name);
3337 free (pkg_name);
3340 static const char **source_refs = NULL;
3341 static int source_refs_used = 0;
3342 static int source_refs_allocd = 0;
3344 /* Add an entry for FILENAME to the table SOURCE_REFS. */
3346 void
3347 collect_source_ref (const char *filename)
3349 int i;
3351 if (!filename)
3352 return;
3354 if (source_refs_allocd == 0)
3356 source_refs_allocd = 1024;
3357 source_refs = XNEWVEC (const char *, source_refs_allocd);
3360 for (i = 0; i < source_refs_used; i++)
3361 if (filename == source_refs[i])
3362 return;
3364 if (source_refs_used == source_refs_allocd)
3366 source_refs_allocd *= 2;
3367 source_refs = XRESIZEVEC (const char *, source_refs, source_refs_allocd);
3370 source_refs[source_refs_used++] = filename;
3373 /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
3374 using callbacks COLLECT_ALL_REFS and CPP_CHECK.
3375 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3376 nodes for a given source file.
3377 CPP_CHECK is used to perform C++ queries on nodes, or NULL for the C
3378 front-end. */
3380 void
3381 dump_ada_specs (void (*collect_all_refs)(const char *),
3382 int (*cpp_check)(tree, cpp_operation))
3384 int i;
3386 /* Iterate over the list of files to dump specs for */
3387 for (i = 0; i < source_refs_used; i++)
3388 dump_ads (source_refs[i], collect_all_refs, cpp_check);
3390 /* Free files table. */
3391 free (source_refs);