PR fortran/47894
[official-gcc.git] / gcc / c-family / c-ada-spec.c
blob335acb0e3256397cf0e9dce18216bc4496ccac89
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 "tree-pass.h" /* For TDI_ada and friends. */
28 #include "output.h"
29 #include "c-ada-spec.h"
30 #include "cpplib.h"
31 #include "c-pragma.h"
32 #include "cpp-id-data.h"
34 /* Local functions, macros and variables. */
35 static int dump_generic_ada_node (pretty_printer *, tree, tree,
36 int (*)(tree, cpp_operation), int, int, bool);
37 static int print_ada_declaration (pretty_printer *, tree, tree,
38 int (*cpp_check)(tree, cpp_operation), int);
39 static void print_ada_struct_decl (pretty_printer *, tree, tree,
40 int (*cpp_check)(tree, cpp_operation), int,
41 bool);
42 static void dump_sloc (pretty_printer *buffer, tree node);
43 static void print_comment (pretty_printer *, const char *);
44 static void print_generic_ada_decl (pretty_printer *, tree,
45 int (*)(tree, cpp_operation), const char *);
46 static char *get_ada_package (const char *);
47 static void dump_ada_nodes (pretty_printer *, const char *,
48 int (*)(tree, cpp_operation));
49 static void reset_ada_withs (void);
50 static void dump_ada_withs (FILE *);
51 static void dump_ads (const char *, void (*)(const char *),
52 int (*)(tree, cpp_operation));
53 static char *to_ada_name (const char *, int *);
54 static bool separate_class_package (tree);
56 #define LOCATION_COL(LOC) ((expand_location (LOC)).column)
58 #define INDENT(SPACE) do { \
59 int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
61 #define INDENT_INCR 3
63 /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
64 as max length PARAM_LEN of arguments for fun_like macros, and also set
65 SUPPORTED to 0 if the macro cannot be mapped to an Ada construct. */
67 static void
68 macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
69 int *param_len)
71 int i;
72 unsigned j;
74 *supported = 1;
75 *buffer_len = 0;
76 *param_len = 0;
78 if (macro->fun_like)
80 param_len++;
81 for (i = 0; i < macro->paramc; i++)
83 cpp_hashnode *param = macro->params[i];
85 *param_len += NODE_LEN (param);
87 if (i + 1 < macro->paramc)
89 *param_len += 2; /* ", " */
91 else if (macro->variadic)
93 *supported = 0;
94 return;
97 *param_len += 2; /* ")\0" */
100 for (j = 0; j < macro->count; j++)
102 cpp_token *token = &macro->exp.tokens[j];
104 if (token->flags & PREV_WHITE)
105 (*buffer_len)++;
107 if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
109 *supported = 0;
110 return;
113 if (token->type == CPP_MACRO_ARG)
114 *buffer_len +=
115 NODE_LEN (macro->params[token->val.macro_arg.arg_no - 1]);
116 else
117 /* Include enough extra space to handle e.g. special characters. */
118 *buffer_len += (cpp_token_len (token) + 1) * 8;
121 (*buffer_len)++;
124 /* Dump into PP a set of MAX_ADA_MACROS MACROS (C/C++) as Ada constants when
125 possible. */
127 static void
128 print_ada_macros (pretty_printer *pp, cpp_hashnode **macros, int max_ada_macros)
130 int j, num_macros = 0, prev_line = -1;
132 for (j = 0; j < max_ada_macros; j++)
134 cpp_hashnode *node = macros [j];
135 const cpp_macro *macro = node->value.macro;
136 unsigned i;
137 int supported = 1, prev_is_one = 0, buffer_len, param_len;
138 int is_string = 0, is_char = 0;
139 char *ada_name;
140 unsigned char *s, *params, *buffer, *buf_param, *char_one = NULL;
142 macro_length (macro, &supported, &buffer_len, &param_len);
143 s = buffer = XALLOCAVEC (unsigned char, buffer_len);
144 params = buf_param = XALLOCAVEC (unsigned char, param_len);
146 if (supported)
148 if (macro->fun_like)
150 *buf_param++ = '(';
151 for (i = 0; i < macro->paramc; i++)
153 cpp_hashnode *param = macro->params[i];
155 memcpy (buf_param, NODE_NAME (param), NODE_LEN (param));
156 buf_param += NODE_LEN (param);
158 if (i + 1 < macro->paramc)
160 *buf_param++ = ',';
161 *buf_param++ = ' ';
163 else if (macro->variadic)
165 supported = 0;
166 break;
169 *buf_param++ = ')';
170 *buf_param = '\0';
173 for (i = 0; supported && i < macro->count; i++)
175 cpp_token *token = &macro->exp.tokens[i];
176 int is_one = 0;
178 if (token->flags & PREV_WHITE)
179 *buffer++ = ' ';
181 if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
183 supported = 0;
184 break;
187 switch (token->type)
189 case CPP_MACRO_ARG:
191 cpp_hashnode *param =
192 macro->params[token->val.macro_arg.arg_no - 1];
193 memcpy (buffer, NODE_NAME (param), NODE_LEN (param));
194 buffer += NODE_LEN (param);
196 break;
198 case CPP_EQ_EQ: *buffer++ = '='; break;
199 case CPP_GREATER: *buffer++ = '>'; break;
200 case CPP_LESS: *buffer++ = '<'; break;
201 case CPP_PLUS: *buffer++ = '+'; break;
202 case CPP_MINUS: *buffer++ = '-'; break;
203 case CPP_MULT: *buffer++ = '*'; break;
204 case CPP_DIV: *buffer++ = '/'; break;
205 case CPP_COMMA: *buffer++ = ','; break;
206 case CPP_OPEN_SQUARE:
207 case CPP_OPEN_PAREN: *buffer++ = '('; break;
208 case CPP_CLOSE_SQUARE: /* fallthrough */
209 case CPP_CLOSE_PAREN: *buffer++ = ')'; break;
210 case CPP_DEREF: /* fallthrough */
211 case CPP_SCOPE: /* fallthrough */
212 case CPP_DOT: *buffer++ = '.'; break;
214 case CPP_EQ: *buffer++ = ':'; *buffer++ = '='; break;
215 case CPP_NOT_EQ: *buffer++ = '/'; *buffer++ = '='; break;
216 case CPP_GREATER_EQ: *buffer++ = '>'; *buffer++ = '='; break;
217 case CPP_LESS_EQ: *buffer++ = '<'; *buffer++ = '='; break;
219 case CPP_NOT:
220 *buffer++ = 'n'; *buffer++ = 'o'; *buffer++ = 't'; break;
221 case CPP_MOD:
222 *buffer++ = 'm'; *buffer++ = 'o'; *buffer++ = 'd'; break;
223 case CPP_AND:
224 *buffer++ = 'a'; *buffer++ = 'n'; *buffer++ = 'd'; break;
225 case CPP_OR:
226 *buffer++ = 'o'; *buffer++ = 'r'; break;
227 case CPP_XOR:
228 *buffer++ = 'x'; *buffer++ = 'o'; *buffer++ = 'r'; break;
229 case CPP_AND_AND:
230 strcpy ((char *) buffer, " and then ");
231 buffer += 10;
232 break;
233 case CPP_OR_OR:
234 strcpy ((char *) buffer, " or else ");
235 buffer += 9;
236 break;
238 case CPP_PADDING:
239 *buffer++ = ' ';
240 is_one = prev_is_one;
241 break;
243 case CPP_COMMENT: break;
245 case CPP_WSTRING:
246 case CPP_STRING16:
247 case CPP_STRING32:
248 case CPP_UTF8STRING:
249 case CPP_WCHAR:
250 case CPP_CHAR16:
251 case CPP_CHAR32:
252 case CPP_NAME:
253 case CPP_STRING:
254 case CPP_NUMBER:
255 if (!macro->fun_like)
256 supported = 0;
257 else
258 buffer = cpp_spell_token (parse_in, token, buffer, false);
259 break;
261 case CPP_CHAR:
262 is_char = 1;
264 unsigned chars_seen;
265 int ignored;
266 cppchar_t c;
268 c = cpp_interpret_charconst (parse_in, token,
269 &chars_seen, &ignored);
270 if (c >= 32 && c <= 126)
272 *buffer++ = '\'';
273 *buffer++ = (char) c;
274 *buffer++ = '\'';
276 else
278 chars_seen = sprintf
279 ((char *) buffer, "Character'Val (%d)", (int) c);
280 buffer += chars_seen;
283 break;
285 case CPP_LSHIFT:
286 if (prev_is_one)
288 /* Replace "1 << N" by "2 ** N" */
289 *char_one = '2';
290 *buffer++ = '*';
291 *buffer++ = '*';
292 break;
294 /* fallthrough */
296 case CPP_RSHIFT:
297 case CPP_COMPL:
298 case CPP_QUERY:
299 case CPP_EOF:
300 case CPP_PLUS_EQ:
301 case CPP_MINUS_EQ:
302 case CPP_MULT_EQ:
303 case CPP_DIV_EQ:
304 case CPP_MOD_EQ:
305 case CPP_AND_EQ:
306 case CPP_OR_EQ:
307 case CPP_XOR_EQ:
308 case CPP_RSHIFT_EQ:
309 case CPP_LSHIFT_EQ:
310 case CPP_PRAGMA:
311 case CPP_PRAGMA_EOL:
312 case CPP_HASH:
313 case CPP_PASTE:
314 case CPP_OPEN_BRACE:
315 case CPP_CLOSE_BRACE:
316 case CPP_SEMICOLON:
317 case CPP_ELLIPSIS:
318 case CPP_PLUS_PLUS:
319 case CPP_MINUS_MINUS:
320 case CPP_DEREF_STAR:
321 case CPP_DOT_STAR:
322 case CPP_ATSIGN:
323 case CPP_HEADER_NAME:
324 case CPP_AT_NAME:
325 case CPP_OTHER:
326 case CPP_OBJC_STRING:
327 default:
328 if (!macro->fun_like)
329 supported = 0;
330 else
331 buffer = cpp_spell_token (parse_in, token, buffer, false);
332 break;
335 prev_is_one = is_one;
338 if (supported)
339 *buffer = '\0';
342 if (macro->fun_like && supported)
344 char *start = (char *) s;
345 int is_function = 0;
347 pp_string (pp, " -- arg-macro: ");
349 if (*start == '(' && buffer [-1] == ')')
351 start++;
352 buffer [-1] = '\0';
353 is_function = 1;
354 pp_string (pp, "function ");
356 else
358 pp_string (pp, "procedure ");
361 pp_string (pp, (const char *) NODE_NAME (node));
362 pp_space (pp);
363 pp_string (pp, (char *) params);
364 pp_newline (pp);
365 pp_string (pp, " -- ");
367 if (is_function)
369 pp_string (pp, "return ");
370 pp_string (pp, start);
371 pp_semicolon (pp);
373 else
374 pp_string (pp, start);
376 pp_newline (pp);
378 else if (supported)
380 expanded_location sloc = expand_location (macro->line);
382 if (sloc.line != prev_line + 1)
383 pp_newline (pp);
385 num_macros++;
386 prev_line = sloc.line;
388 pp_string (pp, " ");
389 ada_name = to_ada_name ((const char *) NODE_NAME (node), NULL);
390 pp_string (pp, ada_name);
391 free (ada_name);
392 pp_string (pp, " : ");
394 if (is_string)
395 pp_string (pp, "aliased constant String");
396 else if (is_char)
397 pp_string (pp, "aliased constant Character");
398 else
399 pp_string (pp, "constant");
401 pp_string (pp, " := ");
402 pp_string (pp, (char *) s);
404 if (is_string)
405 pp_string (pp, " & ASCII.NUL");
407 pp_string (pp, "; -- ");
408 pp_string (pp, sloc.file);
409 pp_character (pp, ':');
410 pp_scalar (pp, "%d", sloc.line);
411 pp_newline (pp);
413 else
415 pp_string (pp, " -- unsupported macro: ");
416 pp_string (pp, (const char *) cpp_macro_definition (parse_in, node));
417 pp_newline (pp);
421 if (num_macros > 0)
422 pp_newline (pp);
425 static const char *source_file;
426 static int max_ada_macros;
428 /* Callback used to count the number of relevant macros from
429 cpp_forall_identifiers. PFILE and V are not used. NODE is the current macro
430 to consider. */
432 static int
433 count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node,
434 void *v ATTRIBUTE_UNUSED)
436 const cpp_macro *macro = node->value.macro;
438 if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
439 && macro->count
440 && *NODE_NAME (node) != '_'
441 && LOCATION_FILE (macro->line) == source_file)
442 max_ada_macros++;
444 return 1;
447 static int store_ada_macro_index;
449 /* Callback used to store relevant macros from cpp_forall_identifiers.
450 PFILE is not used. NODE is the current macro to store if relevant.
451 MACROS is an array of cpp_hashnode* used to store NODE. */
453 static int
454 store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED,
455 cpp_hashnode *node, void *macros)
457 const cpp_macro *macro = node->value.macro;
459 if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
460 && macro->count
461 && *NODE_NAME (node) != '_'
462 && LOCATION_FILE (macro->line) == source_file)
463 ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
465 return 1;
468 /* Callback used to compare (during qsort) macros. NODE1 and NODE2 are the
469 two macro nodes to compare. */
471 static int
472 compare_macro (const void *node1, const void *node2)
474 typedef const cpp_hashnode *const_hnode;
476 const_hnode n1 = *(const const_hnode *) node1;
477 const_hnode n2 = *(const const_hnode *) node2;
479 return n1->value.macro->line - n2->value.macro->line;
482 /* Dump in PP all relevant macros appearing in FILE. */
484 static void
485 dump_ada_macros (pretty_printer *pp, const char* file)
487 cpp_hashnode **macros;
489 /* Initialize file-scope variables. */
490 max_ada_macros = 0;
491 store_ada_macro_index = 0;
492 source_file = file;
494 /* Count all potentially relevant macros, and then sort them by sloc. */
495 cpp_forall_identifiers (parse_in, count_ada_macro, NULL);
496 macros = XALLOCAVEC (cpp_hashnode *, max_ada_macros);
497 cpp_forall_identifiers (parse_in, store_ada_macro, macros);
498 qsort (macros, max_ada_macros, sizeof (cpp_hashnode *), compare_macro);
500 print_ada_macros (pp, macros, max_ada_macros);
503 /* Current source file being handled. */
505 static const char *source_file_base;
507 /* Compare the declaration (DECL) of struct-like types based on the sloc of
508 their last field (if LAST is true), so that more nested types collate before
509 less nested ones.
510 If ORIG_TYPE is true, also consider struct with a DECL_ORIGINAL_TYPE. */
512 static location_t
513 decl_sloc_common (const_tree decl, bool last, bool orig_type)
515 tree type = TREE_TYPE (decl);
517 if (TREE_CODE (decl) == TYPE_DECL
518 && (orig_type || !DECL_ORIGINAL_TYPE (decl))
519 && RECORD_OR_UNION_TYPE_P (type)
520 && TYPE_FIELDS (type))
522 tree f = TYPE_FIELDS (type);
524 if (last)
525 while (TREE_CHAIN (f))
526 f = TREE_CHAIN (f);
528 return DECL_SOURCE_LOCATION (f);
530 else
531 return DECL_SOURCE_LOCATION (decl);
534 /* Return sloc of DECL, using sloc of last field if LAST is true. */
536 location_t
537 decl_sloc (const_tree decl, bool last)
539 return decl_sloc_common (decl, last, false);
542 /* Compare two declarations (LP and RP) by their source location. */
544 static int
545 compare_node (const void *lp, const void *rp)
547 const_tree lhs = *((const tree *) lp);
548 const_tree rhs = *((const tree *) rp);
550 return decl_sloc (lhs, true) - decl_sloc (rhs, true);
553 /* Compare two comments (LP and RP) by their source location. */
555 static int
556 compare_comment (const void *lp, const void *rp)
558 const cpp_comment *lhs = (const cpp_comment *) lp;
559 const cpp_comment *rhs = (const cpp_comment *) rp;
561 if (LOCATION_FILE (lhs->sloc) != LOCATION_FILE (rhs->sloc))
562 return strcmp (LOCATION_FILE (lhs->sloc), LOCATION_FILE (rhs->sloc));
564 if (LOCATION_LINE (lhs->sloc) != LOCATION_LINE (rhs->sloc))
565 return LOCATION_LINE (lhs->sloc) - LOCATION_LINE (rhs->sloc);
567 if (LOCATION_COL (lhs->sloc) != LOCATION_COL (rhs->sloc))
568 return LOCATION_COL (lhs->sloc) - LOCATION_COL (rhs->sloc);
570 return 0;
573 static tree *to_dump = NULL;
574 static int to_dump_count = 0;
576 /* Collect a list of declarations from T relevant to SOURCE_FILE to be dumped
577 by a subsequent call to dump_ada_nodes. */
579 void
580 collect_ada_nodes (tree t, const char *source_file)
582 tree n;
583 int i = to_dump_count;
585 /* Count the likely relevant nodes. */
586 for (n = t; n; n = TREE_CHAIN (n))
587 if (!DECL_IS_BUILTIN (n)
588 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
589 to_dump_count++;
591 /* Allocate sufficient storage for all nodes. */
592 to_dump = XRESIZEVEC (tree, to_dump, to_dump_count);
594 /* Store the relevant nodes. */
595 for (n = t; n; n = TREE_CHAIN (n))
596 if (!DECL_IS_BUILTIN (n)
597 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
598 to_dump [i++] = n;
601 /* Call back for walk_tree to clear the TREE_VISITED flag of TP. */
603 static tree
604 unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
605 void *data ATTRIBUTE_UNUSED)
607 if (TREE_VISITED (*tp))
608 TREE_VISITED (*tp) = 0;
609 else
610 *walk_subtrees = 0;
612 return NULL_TREE;
615 /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
616 to collect_ada_nodes. CPP_CHECK is used to perform C++ queries on nodes. */
618 static void
619 dump_ada_nodes (pretty_printer *pp, const char *source_file,
620 int (*cpp_check)(tree, cpp_operation))
622 int i, j;
623 cpp_comment_table *comments;
625 /* Sort the table of declarations to dump by sloc. */
626 qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
628 /* Fetch the table of comments. */
629 comments = cpp_get_comments (parse_in);
631 /* Sort the comments table by sloc. */
632 qsort (comments->entries, comments->count, sizeof (cpp_comment),
633 compare_comment);
635 /* Interleave comments and declarations in line number order. */
636 i = j = 0;
639 /* Advance j until comment j is in this file. */
640 while (j != comments->count
641 && LOCATION_FILE (comments->entries[j].sloc) != source_file)
642 j++;
644 /* Advance j until comment j is not a duplicate. */
645 while (j < comments->count - 1
646 && !compare_comment (&comments->entries[j],
647 &comments->entries[j + 1]))
648 j++;
650 /* Write decls until decl i collates after comment j. */
651 while (i != to_dump_count)
653 if (j == comments->count
654 || LOCATION_LINE (decl_sloc (to_dump[i], false))
655 < LOCATION_LINE (comments->entries[j].sloc))
656 print_generic_ada_decl (pp, to_dump[i++], cpp_check, source_file);
657 else
658 break;
661 /* Write comment j, if there is one. */
662 if (j != comments->count)
663 print_comment (pp, comments->entries[j++].comment);
665 } while (i != to_dump_count || j != comments->count);
667 /* Clear the TREE_VISITED flag over each subtree we've dumped. */
668 for (i = 0; i < to_dump_count; i++)
669 walk_tree (&to_dump[i], unmark_visited_r, NULL, NULL);
671 /* Finalize the to_dump table. */
672 if (to_dump)
674 free (to_dump);
675 to_dump = NULL;
676 to_dump_count = 0;
680 /* Print a COMMENT to the output stream PP. */
682 static void
683 print_comment (pretty_printer *pp, const char *comment)
685 int len = strlen (comment);
686 char *str = XALLOCAVEC (char, len + 1);
687 char *tok;
688 bool extra_newline = false;
690 memcpy (str, comment, len + 1);
692 /* Trim C/C++ comment indicators. */
693 if (str[len - 2] == '*' && str[len - 1] == '/')
695 str[len - 2] = ' ';
696 str[len - 1] = '\0';
698 str += 2;
700 tok = strtok (str, "\n");
701 while (tok) {
702 pp_string (pp, " --");
703 pp_string (pp, tok);
704 pp_newline (pp);
705 tok = strtok (NULL, "\n");
707 /* Leave a blank line after multi-line comments. */
708 if (tok)
709 extra_newline = true;
712 if (extra_newline)
713 pp_newline (pp);
716 /* Prints declaration DECL to PP in Ada syntax. The current source file being
717 handled is SOURCE_FILE, and CPP_CHECK is used to perform C++ queries on
718 nodes. */
720 static void
721 print_generic_ada_decl (pretty_printer *pp, tree decl,
722 int (*cpp_check)(tree, cpp_operation),
723 const char* source_file)
725 source_file_base = source_file;
727 if (print_ada_declaration (pp, decl, 0, cpp_check, INDENT_INCR))
729 pp_newline (pp);
730 pp_newline (pp);
734 /* Dump a newline and indent BUFFER by SPC chars. */
736 static void
737 newline_and_indent (pretty_printer *buffer, int spc)
739 pp_newline (buffer);
740 INDENT (spc);
743 struct with { char *s; const char *in_file; int limited; };
744 static struct with *withs = NULL;
745 static int withs_max = 4096;
746 static int with_len = 0;
748 /* Record a "with" clause on package S (a limited with if LIMITED_ACCESS is
749 true), if not already done. */
751 static void
752 append_withs (const char *s, int limited_access)
754 int i;
756 if (withs == NULL)
757 withs = XNEWVEC (struct with, withs_max);
759 if (with_len == withs_max)
761 withs_max *= 2;
762 withs = XRESIZEVEC (struct with, withs, withs_max);
765 for (i = 0; i < with_len; i++)
766 if (!strcmp (s, withs [i].s)
767 && source_file_base == withs [i].in_file)
769 withs [i].limited &= limited_access;
770 return;
773 withs [with_len].s = xstrdup (s);
774 withs [with_len].in_file = source_file_base;
775 withs [with_len].limited = limited_access;
776 with_len++;
779 /* Reset "with" clauses. */
781 static void
782 reset_ada_withs (void)
784 int i;
786 if (!withs)
787 return;
789 for (i = 0; i < with_len; i++)
790 free (withs [i].s);
791 free (withs);
792 withs = NULL;
793 withs_max = 4096;
794 with_len = 0;
797 /* Dump "with" clauses in F. */
799 static void
800 dump_ada_withs (FILE *f)
802 int i;
804 fprintf (f, "with Interfaces.C; use Interfaces.C;\n");
806 for (i = 0; i < with_len; i++)
807 fprintf
808 (f, "%swith %s;\n", withs [i].limited ? "limited " : "", withs [i].s);
811 /* Return suitable Ada package name from FILE. */
813 static char *
814 get_ada_package (const char *file)
816 const char *base;
817 char *res;
818 const char *s;
819 int i;
821 s = strstr (file, "/include/");
822 if (s)
823 base = s + 9;
824 else
825 base = lbasename (file);
826 res = XNEWVEC (char, strlen (base) + 1);
828 for (i = 0; *base; base++, i++)
829 switch (*base)
831 case '+':
832 res [i] = 'p';
833 break;
835 case '.':
836 case '-':
837 case '_':
838 case '/':
839 case '\\':
840 res [i] = (i == 0 || res [i - 1] == '_') ? 'u' : '_';
841 break;
843 default:
844 res [i] = *base;
845 break;
847 res [i] = '\0';
849 return res;
852 static const char *ada_reserved[] = {
853 "abort", "abs", "abstract", "accept", "access", "aliased", "all", "and",
854 "array", "at", "begin", "body", "case", "constant", "declare", "delay",
855 "delta", "digits", "do", "else", "elsif", "end", "entry", "exception",
856 "exit", "for", "function", "generic", "goto", "if", "in", "interface", "is",
857 "limited", "loop", "mod", "new", "not", "null", "others", "out", "of", "or",
858 "overriding", "package", "pragma", "private", "procedure", "protected",
859 "raise", "range", "record", "rem", "renames", "requeue", "return", "reverse",
860 "select", "separate", "subtype", "synchronized", "tagged", "task",
861 "terminate", "then", "type", "until", "use", "when", "while", "with", "xor",
862 NULL};
864 /* ??? would be nice to specify this list via a config file, so that users
865 can create their own dictionary of conflicts. */
866 static const char *c_duplicates[] = {
867 /* system will cause troubles with System.Address. */
868 "system",
870 /* The following values have other definitions with same name/other
871 casing. */
872 "funmap",
873 "rl_vi_fWord",
874 "rl_vi_bWord",
875 "rl_vi_eWord",
876 "rl_readline_version",
877 "_Vx_ushort",
878 "USHORT",
879 "XLookupKeysym",
880 NULL};
882 /* Return a declaration tree corresponding to TYPE. */
884 static tree
885 get_underlying_decl (tree type)
887 tree decl = NULL_TREE;
889 if (type == NULL_TREE)
890 return NULL_TREE;
892 /* type is a declaration. */
893 if (DECL_P (type))
894 decl = type;
896 /* type is a typedef. */
897 if (TYPE_P (type) && TYPE_NAME (type) && DECL_P (TYPE_NAME (type)))
898 decl = TYPE_NAME (type);
900 /* TYPE_STUB_DECL has been set for type. */
901 if (TYPE_P (type) && TYPE_STUB_DECL (type) &&
902 DECL_P (TYPE_STUB_DECL (type)))
903 decl = TYPE_STUB_DECL (type);
905 return decl;
908 /* Return whether TYPE has static fields. */
910 static int
911 has_static_fields (const_tree type)
913 tree tmp;
915 for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
917 if (DECL_NAME (tmp) && TREE_STATIC (tmp))
918 return true;
920 return false;
923 /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
924 table). */
926 static int
927 is_tagged_type (const_tree type)
929 tree tmp;
931 if (!type || !RECORD_OR_UNION_TYPE_P (type))
932 return false;
934 for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
935 if (DECL_VINDEX (tmp))
936 return true;
938 return false;
941 /* Generate a legal Ada name from a C NAME, returning a malloc'd string.
942 SPACE_FOUND, if not NULL, is used to indicate whether a space was found in
943 NAME. */
945 static char *
946 to_ada_name (const char *name, int *space_found)
948 const char **names;
949 int len = strlen (name);
950 int j, len2 = 0;
951 int found = false;
952 char *s = XNEWVEC (char, len * 2 + 5);
953 char c;
955 if (space_found)
956 *space_found = false;
958 /* Add trailing "c_" if name is an Ada reserved word. */
959 for (names = ada_reserved; *names; names++)
960 if (!strcasecmp (name, *names))
962 s [len2++] = 'c';
963 s [len2++] = '_';
964 found = true;
965 break;
968 if (!found)
969 /* Add trailing "c_" if name is an potential case sensitive duplicate. */
970 for (names = c_duplicates; *names; names++)
971 if (!strcmp (name, *names))
973 s [len2++] = 'c';
974 s [len2++] = '_';
975 found = true;
976 break;
979 for (j = 0; name [j] == '_'; j++)
980 s [len2++] = 'u';
982 if (j > 0)
983 s [len2++] = '_';
984 else if (*name == '.' || *name == '$')
986 s [0] = 'a';
987 s [1] = 'n';
988 s [2] = 'o';
989 s [3] = 'n';
990 len2 = 4;
991 j++;
994 /* Replace unsuitable characters for Ada identifiers. */
996 for (; j < len; j++)
997 switch (name [j])
999 case ' ':
1000 if (space_found)
1001 *space_found = true;
1002 s [len2++] = '_';
1003 break;
1005 /* ??? missing some C++ operators. */
1006 case '=':
1007 s [len2++] = '_';
1009 if (name [j + 1] == '=')
1011 j++;
1012 s [len2++] = 'e';
1013 s [len2++] = 'q';
1015 else
1017 s [len2++] = 'a';
1018 s [len2++] = 's';
1020 break;
1022 case '!':
1023 s [len2++] = '_';
1024 if (name [j + 1] == '=')
1026 j++;
1027 s [len2++] = 'n';
1028 s [len2++] = 'e';
1030 break;
1032 case '~':
1033 s [len2++] = '_';
1034 s [len2++] = 't';
1035 s [len2++] = 'i';
1036 break;
1038 case '&':
1039 case '|':
1040 case '^':
1041 s [len2++] = '_';
1042 s [len2++] = name [j] == '&' ? 'a' : name [j] == '|' ? 'o' : 'x';
1044 if (name [j + 1] == '=')
1046 j++;
1047 s [len2++] = 'e';
1049 break;
1051 case '+':
1052 case '-':
1053 case '*':
1054 case '/':
1055 case '(':
1056 case '[':
1057 if (s [len2 - 1] != '_')
1058 s [len2++] = '_';
1060 switch (name [j + 1]) {
1061 case '\0':
1062 j++;
1063 switch (name [j - 1]) {
1064 case '+': s [len2++] = 'p'; break; /* + */
1065 case '-': s [len2++] = 'm'; break; /* - */
1066 case '*': s [len2++] = 't'; break; /* * */
1067 case '/': s [len2++] = 'd'; break; /* / */
1069 break;
1071 case '=':
1072 j++;
1073 switch (name [j - 1]) {
1074 case '+': s [len2++] = 'p'; break; /* += */
1075 case '-': s [len2++] = 'm'; break; /* -= */
1076 case '*': s [len2++] = 't'; break; /* *= */
1077 case '/': s [len2++] = 'd'; break; /* /= */
1079 s [len2++] = 'a';
1080 break;
1082 case '-': /* -- */
1083 j++;
1084 s [len2++] = 'm';
1085 s [len2++] = 'm';
1086 break;
1088 case '+': /* ++ */
1089 j++;
1090 s [len2++] = 'p';
1091 s [len2++] = 'p';
1092 break;
1094 case ')': /* () */
1095 j++;
1096 s [len2++] = 'o';
1097 s [len2++] = 'p';
1098 break;
1100 case ']': /* [] */
1101 j++;
1102 s [len2++] = 'o';
1103 s [len2++] = 'b';
1104 break;
1107 break;
1109 case '<':
1110 case '>':
1111 c = name [j] == '<' ? 'l' : 'g';
1112 s [len2++] = '_';
1114 switch (name [j + 1]) {
1115 case '\0':
1116 s [len2++] = c;
1117 s [len2++] = 't';
1118 break;
1119 case '=':
1120 j++;
1121 s [len2++] = c;
1122 s [len2++] = 'e';
1123 break;
1124 case '>':
1125 j++;
1126 s [len2++] = 's';
1127 s [len2++] = 'r';
1128 break;
1129 case '<':
1130 j++;
1131 s [len2++] = 's';
1132 s [len2++] = 'l';
1133 break;
1134 default:
1135 break;
1137 break;
1139 case '_':
1140 if (len2 && s [len2 - 1] == '_')
1141 s [len2++] = 'u';
1142 /* fall through */
1144 default:
1145 s [len2++] = name [j];
1148 if (s [len2 - 1] == '_')
1149 s [len2++] = 'u';
1151 s [len2] = '\0';
1153 return s;
1156 /* Return true if DECL refers to a C++ class type for which a
1157 separate enclosing package has been or should be generated. */
1159 static bool
1160 separate_class_package (tree decl)
1162 if (decl)
1164 tree type = TREE_TYPE (decl);
1165 return type
1166 && TREE_CODE (type) == RECORD_TYPE
1167 && (TYPE_METHODS (type) || has_static_fields (type));
1169 else
1170 return false;
1173 static bool package_prefix = true;
1175 /* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
1176 syntax. LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1177 'with' clause rather than a regular 'with' clause. */
1179 static void
1180 pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
1181 int limited_access)
1183 const char *name = IDENTIFIER_POINTER (node);
1184 int space_found = false;
1185 char *s = to_ada_name (name, &space_found);
1186 tree decl;
1188 /* If the entity is a type and comes from another file, generate "package"
1189 prefix. */
1191 decl = get_underlying_decl (type);
1193 if (decl)
1195 expanded_location xloc = expand_location (decl_sloc (decl, false));
1197 if (xloc.file && xloc.line)
1199 if (xloc.file != source_file_base)
1201 switch (TREE_CODE (type))
1203 case ENUMERAL_TYPE:
1204 case INTEGER_TYPE:
1205 case REAL_TYPE:
1206 case FIXED_POINT_TYPE:
1207 case BOOLEAN_TYPE:
1208 case REFERENCE_TYPE:
1209 case POINTER_TYPE:
1210 case ARRAY_TYPE:
1211 case RECORD_TYPE:
1212 case UNION_TYPE:
1213 case QUAL_UNION_TYPE:
1214 case TYPE_DECL:
1216 char *s1 = get_ada_package (xloc.file);
1218 if (package_prefix)
1220 append_withs (s1, limited_access);
1221 pp_string (buffer, s1);
1222 pp_character (buffer, '.');
1224 free (s1);
1226 break;
1227 default:
1228 break;
1231 if (separate_class_package (decl))
1233 pp_string (buffer, "Class_");
1234 pp_string (buffer, s);
1235 pp_string (buffer, ".");
1242 if (space_found)
1243 if (!strcmp (s, "short_int"))
1244 pp_string (buffer, "short");
1245 else if (!strcmp (s, "short_unsigned_int"))
1246 pp_string (buffer, "unsigned_short");
1247 else if (!strcmp (s, "unsigned_int"))
1248 pp_string (buffer, "unsigned");
1249 else if (!strcmp (s, "long_int"))
1250 pp_string (buffer, "long");
1251 else if (!strcmp (s, "long_unsigned_int"))
1252 pp_string (buffer, "unsigned_long");
1253 else if (!strcmp (s, "long_long_int"))
1254 pp_string (buffer, "Long_Long_Integer");
1255 else if (!strcmp (s, "long_long_unsigned_int"))
1257 if (package_prefix)
1259 append_withs ("Interfaces.C.Extensions", false);
1260 pp_string (buffer, "Extensions.unsigned_long_long");
1262 else
1263 pp_string (buffer, "unsigned_long_long");
1265 else
1266 pp_string(buffer, s);
1267 else
1268 if (!strcmp (s, "bool"))
1270 if (package_prefix)
1272 append_withs ("Interfaces.C.Extensions", false);
1273 pp_string (buffer, "Extensions.bool");
1275 else
1276 pp_string (buffer, "bool");
1278 else
1279 pp_string(buffer, s);
1281 free (s);
1284 /* Dump in BUFFER the assembly name of T. */
1286 static void
1287 pp_asm_name (pretty_printer *buffer, tree t)
1289 tree name = DECL_ASSEMBLER_NAME (t);
1290 char *ada_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (name) + 1), *s;
1291 const char *ident = IDENTIFIER_POINTER (name);
1293 for (s = ada_name; *ident; ident++)
1295 if (*ident == ' ')
1296 break;
1297 else if (*ident != '*')
1298 *s++ = *ident;
1301 *s = '\0';
1302 pp_string (buffer, ada_name);
1305 /* Dump in BUFFER the name of a DECL node if set, following Ada syntax.
1306 LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1307 'with' clause rather than a regular 'with' clause. */
1309 static void
1310 dump_ada_decl_name (pretty_printer *buffer, tree decl, int limited_access)
1312 if (DECL_NAME (decl))
1313 pp_ada_tree_identifier (buffer, DECL_NAME (decl), decl, limited_access);
1314 else
1316 tree type_name = TYPE_NAME (TREE_TYPE (decl));
1318 if (!type_name)
1320 pp_string (buffer, "anon");
1321 if (TREE_CODE (decl) == FIELD_DECL)
1322 pp_scalar (buffer, "%d", DECL_UID (decl));
1323 else
1324 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (decl)));
1326 else if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1327 pp_ada_tree_identifier (buffer, type_name, decl, limited_access);
1331 /* Dump in BUFFER a name based on both T1 and T2, followed by S. */
1333 static void
1334 dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2, const char *s)
1336 if (DECL_NAME (t1))
1337 pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, false);
1338 else
1340 pp_string (buffer, "anon");
1341 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t1)));
1344 pp_character (buffer, '_');
1346 if (DECL_NAME (t1))
1347 pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, false);
1348 else
1350 pp_string (buffer, "anon");
1351 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t2)));
1354 pp_string (buffer, s);
1357 /* Dump in BUFFER pragma Import C/CPP on a given node T. */
1359 static void
1360 dump_ada_import (pretty_printer *buffer, tree t)
1362 const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
1363 int is_stdcall = TREE_CODE (t) == FUNCTION_DECL &&
1364 lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (t)));
1366 if (is_stdcall)
1367 pp_string (buffer, "pragma Import (Stdcall, ");
1368 else if (name [0] == '_' && name [1] == 'Z')
1369 pp_string (buffer, "pragma Import (CPP, ");
1370 else
1371 pp_string (buffer, "pragma Import (C, ");
1373 dump_ada_decl_name (buffer, t, false);
1374 pp_string (buffer, ", \"");
1376 if (is_stdcall)
1377 pp_string (buffer, IDENTIFIER_POINTER (DECL_NAME (t)));
1378 else
1379 pp_asm_name (buffer, t);
1381 pp_string (buffer, "\");");
1384 /* Check whether T and its type have different names, and append "the_"
1385 otherwise in BUFFER. */
1387 static void
1388 check_name (pretty_printer *buffer, tree t)
1390 const char *s;
1391 tree tmp = TREE_TYPE (t);
1393 while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp))
1394 tmp = TREE_TYPE (tmp);
1396 if (TREE_CODE (tmp) != FUNCTION_TYPE)
1398 if (TREE_CODE (tmp) == IDENTIFIER_NODE)
1399 s = IDENTIFIER_POINTER (tmp);
1400 else if (!TYPE_NAME (tmp))
1401 s = "";
1402 else if (TREE_CODE (TYPE_NAME (tmp)) == IDENTIFIER_NODE)
1403 s = IDENTIFIER_POINTER (TYPE_NAME (tmp));
1404 else
1405 s = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp)));
1407 if (!strcasecmp (IDENTIFIER_POINTER (DECL_NAME (t)), s))
1408 pp_string (buffer, "the_");
1412 /* Dump in BUFFER a function declaration FUNC with Ada syntax.
1413 IS_METHOD indicates whether FUNC is a C++ method.
1414 IS_CONSTRUCTOR whether FUNC is a C++ constructor.
1415 IS_DESTRUCTOR whether FUNC is a C++ destructor.
1416 SPC is the current indentation level. */
1418 static int
1419 dump_ada_function_declaration (pretty_printer *buffer, tree func,
1420 int is_method, int is_constructor,
1421 int is_destructor, int spc)
1423 tree arg;
1424 const tree node = TREE_TYPE (func);
1425 char buf [16];
1426 int num = 0, num_args = 0, have_args = true, have_ellipsis = false;
1428 /* Compute number of arguments. */
1429 arg = TYPE_ARG_TYPES (node);
1431 if (arg)
1433 while (TREE_CHAIN (arg) && arg != error_mark_node)
1435 num_args++;
1436 arg = TREE_CHAIN (arg);
1439 if (TREE_CODE (TREE_VALUE (arg)) != VOID_TYPE)
1441 num_args++;
1442 have_ellipsis = true;
1446 if (is_constructor)
1447 num_args--;
1449 if (is_destructor)
1450 num_args = 1;
1452 if (num_args > 2)
1453 newline_and_indent (buffer, spc + 1);
1455 if (num_args > 0)
1457 pp_space (buffer);
1458 pp_character (buffer, '(');
1461 if (TREE_CODE (func) == FUNCTION_DECL)
1462 arg = DECL_ARGUMENTS (func);
1463 else
1464 arg = NULL_TREE;
1466 if (arg == NULL_TREE)
1468 have_args = false;
1469 arg = TYPE_ARG_TYPES (node);
1471 if (arg && TREE_CODE (TREE_VALUE (arg)) == VOID_TYPE)
1472 arg = NULL_TREE;
1475 if (is_constructor)
1476 arg = TREE_CHAIN (arg);
1478 /* Print the argument names (if available) & types. */
1480 for (num = 1; num <= num_args; num++)
1482 if (have_args)
1484 if (DECL_NAME (arg))
1486 check_name (buffer, arg);
1487 pp_ada_tree_identifier (buffer, DECL_NAME (arg), 0, false);
1488 pp_string (buffer, " : ");
1490 else
1492 sprintf (buf, "arg%d : ", num);
1493 pp_string (buffer, buf);
1496 dump_generic_ada_node
1497 (buffer, TREE_TYPE (arg), node, NULL, spc, 0, true);
1499 else
1501 sprintf (buf, "arg%d : ", num);
1502 pp_string (buffer, buf);
1503 dump_generic_ada_node
1504 (buffer, TREE_VALUE (arg), node, NULL, spc, 0, true);
1507 if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg))
1508 && is_tagged_type (TREE_TYPE (TREE_TYPE (arg))))
1510 if (!is_method
1511 || (num != 1 || (!DECL_VINDEX (func) && !is_constructor)))
1512 pp_string (buffer, "'Class");
1515 arg = TREE_CHAIN (arg);
1517 if (num < num_args)
1519 pp_character (buffer, ';');
1521 if (num_args > 2)
1522 newline_and_indent (buffer, spc + INDENT_INCR);
1523 else
1524 pp_space (buffer);
1528 if (have_ellipsis)
1530 pp_string (buffer, " -- , ...");
1531 newline_and_indent (buffer, spc + INDENT_INCR);
1534 if (num_args > 0)
1535 pp_character (buffer, ')');
1536 return num_args;
1539 /* Dump in BUFFER all the domains associated with an array NODE,
1540 using Ada syntax. SPC is the current indentation level. */
1542 static void
1543 dump_ada_array_domains (pretty_printer *buffer, tree node, int spc)
1545 int first = 1;
1546 pp_character (buffer, '(');
1548 for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node))
1550 tree domain = TYPE_DOMAIN (node);
1552 if (domain)
1554 tree min = TYPE_MIN_VALUE (domain);
1555 tree max = TYPE_MAX_VALUE (domain);
1557 if (!first)
1558 pp_string (buffer, ", ");
1559 first = 0;
1561 if (min)
1562 dump_generic_ada_node (buffer, min, NULL_TREE, NULL, spc, 0, true);
1563 pp_string (buffer, " .. ");
1565 /* If the upper bound is zero, gcc may generate a NULL_TREE
1566 for TYPE_MAX_VALUE rather than an integer_cst. */
1567 if (max)
1568 dump_generic_ada_node (buffer, max, NULL_TREE, NULL, spc, 0, true);
1569 else
1570 pp_string (buffer, "0");
1572 else
1573 pp_string (buffer, "size_t");
1575 pp_character (buffer, ')');
1578 /* Dump in BUFFER file:line information related to NODE. */
1580 static void
1581 dump_sloc (pretty_printer *buffer, tree node)
1583 expanded_location xloc;
1585 xloc.file = NULL;
1587 if (TREE_CODE_CLASS (TREE_CODE (node)) == tcc_declaration)
1588 xloc = expand_location (DECL_SOURCE_LOCATION (node));
1589 else if (EXPR_HAS_LOCATION (node))
1590 xloc = expand_location (EXPR_LOCATION (node));
1592 if (xloc.file)
1594 pp_string (buffer, xloc.file);
1595 pp_string (buffer, ":");
1596 pp_decimal_int (buffer, xloc.line);
1600 /* Return true if T designates a one dimension array of "char". */
1602 static bool
1603 is_char_array (tree t)
1605 tree tmp;
1606 int num_dim = 0;
1608 /* Retrieve array's type. */
1609 tmp = t;
1610 while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1612 num_dim++;
1613 tmp = TREE_TYPE (tmp);
1616 tmp = TREE_TYPE (tmp);
1617 return num_dim == 1 && TREE_CODE (tmp) == INTEGER_TYPE
1618 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp))), "char");
1621 /* Dump in BUFFER an array type T in Ada syntax. Assume that the "type"
1622 keyword and name have already been printed. SPC is the indentation
1623 level. */
1625 static void
1626 dump_ada_array_type (pretty_printer *buffer, tree t, int spc)
1628 tree tmp;
1629 bool char_array = is_char_array (t);
1631 /* Special case char arrays. */
1632 if (char_array)
1634 pp_string (buffer, "Interfaces.C.char_array ");
1636 else
1637 pp_string (buffer, "array ");
1639 /* Print the dimensions. */
1640 dump_ada_array_domains (buffer, TREE_TYPE (t), spc);
1642 /* Retrieve array's type. */
1643 tmp = TREE_TYPE (t);
1644 while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1645 tmp = TREE_TYPE (tmp);
1647 /* Print array's type. */
1648 if (!char_array)
1650 pp_string (buffer, " of ");
1652 if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE)
1653 pp_string (buffer, "aliased ");
1655 dump_generic_ada_node
1656 (buffer, TREE_TYPE (tmp), TREE_TYPE (t), NULL, spc, false, true);
1660 /* Dump in BUFFER type names associated with a template, each prepended with
1661 '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.
1662 CPP_CHECK is used to perform C++ queries on nodes.
1663 SPC is the indentation level. */
1665 static void
1666 dump_template_types (pretty_printer *buffer, tree types,
1667 int (*cpp_check)(tree, cpp_operation), int spc)
1669 size_t i;
1670 size_t len = TREE_VEC_LENGTH (types);
1672 for (i = 0; i < len; i++)
1674 tree elem = TREE_VEC_ELT (types, i);
1675 pp_character (buffer, '_');
1676 if (!dump_generic_ada_node (buffer, elem, 0, cpp_check, spc, false, true))
1678 pp_string (buffer, "unknown");
1679 pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
1684 /* Dump in BUFFER the contents of all instantiations associated with a given
1685 template T. CPP_CHECK is used to perform C++ queries on nodes.
1686 SPC is the indentation level. */
1688 static int
1689 dump_ada_template (pretty_printer *buffer, tree t,
1690 int (*cpp_check)(tree, cpp_operation), int spc)
1692 tree inst = DECL_VINDEX (t);
1693 /* DECL_VINDEX is DECL_TEMPLATE_INSTANTIATIONS in this context. */
1694 int num_inst = 0;
1696 while (inst && inst != error_mark_node)
1698 tree types = TREE_PURPOSE (inst);
1699 tree instance = TREE_VALUE (inst);
1701 if (TREE_VEC_LENGTH (types) == 0)
1702 break;
1704 if (!TYPE_METHODS (instance))
1705 break;
1707 num_inst++;
1708 INDENT (spc);
1709 pp_string (buffer, "package ");
1710 package_prefix = false;
1711 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1712 dump_template_types (buffer, types, cpp_check, spc);
1713 pp_string (buffer, " is");
1714 spc += INDENT_INCR;
1715 newline_and_indent (buffer, spc);
1717 TREE_VISITED (get_underlying_decl (instance)) = 1;
1718 pp_string (buffer, "type ");
1719 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1720 package_prefix = true;
1722 if (is_tagged_type (instance))
1723 pp_string (buffer, " is tagged limited ");
1724 else
1725 pp_string (buffer, " is limited ");
1727 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, false);
1728 pp_newline (buffer);
1729 spc -= INDENT_INCR;
1730 newline_and_indent (buffer, spc);
1732 pp_string (buffer, "end;");
1733 newline_and_indent (buffer, spc);
1734 pp_string (buffer, "use ");
1735 package_prefix = false;
1736 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1737 dump_template_types (buffer, types, cpp_check, spc);
1738 package_prefix = true;
1739 pp_semicolon (buffer);
1740 pp_newline (buffer);
1741 pp_newline (buffer);
1743 inst = TREE_CHAIN (inst);
1746 return num_inst > 0;
1749 /* Return true if NODE is a simple enum types, that can be mapped to an
1750 Ada enum type directly. */
1752 static bool
1753 is_simple_enum (tree node)
1755 unsigned HOST_WIDE_INT count = 0;
1756 tree value;
1758 for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
1760 tree int_val = TREE_VALUE (value);
1762 if (TREE_CODE (int_val) != INTEGER_CST)
1763 int_val = DECL_INITIAL (int_val);
1765 if (!host_integerp (int_val, 0))
1766 return false;
1767 else if (TREE_INT_CST_LOW (int_val) != count)
1768 return false;
1770 count++;
1773 return true;
1776 static bool in_function = true;
1777 static bool bitfield_used = false;
1779 /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
1780 TYPE. CPP_CHECK is used to perform C++ queries on nodes. SPC is the
1781 indentation level. LIMITED_ACCESS indicates whether NODE can be referenced
1782 via a "limited with" clause. NAME_ONLY indicates whether we should only
1783 dump the name of NODE, instead of its full declaration. */
1785 static int
1786 dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
1787 int (*cpp_check)(tree, cpp_operation), int spc,
1788 int limited_access, bool name_only)
1790 if (node == NULL_TREE)
1791 return 0;
1793 switch (TREE_CODE (node))
1795 case ERROR_MARK:
1796 pp_string (buffer, "<<< error >>>");
1797 return 0;
1799 case IDENTIFIER_NODE:
1800 pp_ada_tree_identifier (buffer, node, type, limited_access);
1801 break;
1803 case TREE_LIST:
1804 pp_string (buffer, "--- unexpected node: TREE_LIST");
1805 return 0;
1807 case TREE_BINFO:
1808 dump_generic_ada_node
1809 (buffer, BINFO_TYPE (node), type, cpp_check,
1810 spc, limited_access, name_only);
1812 case TREE_VEC:
1813 pp_string (buffer, "--- unexpected node: TREE_VEC");
1814 return 0;
1816 case VOID_TYPE:
1817 if (package_prefix)
1819 append_withs ("System", false);
1820 pp_string (buffer, "System.Address");
1822 else
1823 pp_string (buffer, "address");
1824 break;
1826 case VECTOR_TYPE:
1827 pp_string (buffer, "<vector>");
1828 break;
1830 case COMPLEX_TYPE:
1831 pp_string (buffer, "<complex>");
1832 break;
1834 case ENUMERAL_TYPE:
1835 if (name_only)
1836 dump_generic_ada_node
1837 (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true);
1838 else
1840 tree value = TYPE_VALUES (node);
1842 if (is_simple_enum (node))
1844 bool first = true;
1845 spc += INDENT_INCR;
1846 newline_and_indent (buffer, spc - 1);
1847 pp_string (buffer, "(");
1848 for (; value; value = TREE_CHAIN (value))
1850 if (first)
1851 first = false;
1852 else
1854 pp_string (buffer, ",");
1855 newline_and_indent (buffer, spc);
1858 pp_ada_tree_identifier
1859 (buffer, TREE_PURPOSE (value), node, false);
1861 pp_string (buffer, ");");
1862 spc -= INDENT_INCR;
1863 newline_and_indent (buffer, spc);
1864 pp_string (buffer, "pragma Convention (C, ");
1865 dump_generic_ada_node
1866 (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
1867 cpp_check, spc, 0, true);
1868 pp_string (buffer, ")");
1870 else
1872 pp_string (buffer, "unsigned");
1873 for (; value; value = TREE_CHAIN (value))
1875 pp_semicolon (buffer);
1876 newline_and_indent (buffer, spc);
1878 pp_ada_tree_identifier
1879 (buffer, TREE_PURPOSE (value), node, false);
1880 pp_string (buffer, " : constant ");
1882 dump_generic_ada_node
1883 (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
1884 cpp_check, spc, 0, true);
1886 pp_string (buffer, " := ");
1887 dump_generic_ada_node
1888 (buffer,
1889 TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
1890 TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
1891 node, cpp_check, spc, false, true);
1895 break;
1897 case INTEGER_TYPE:
1898 case REAL_TYPE:
1899 case FIXED_POINT_TYPE:
1900 case BOOLEAN_TYPE:
1902 enum tree_code_class tclass;
1904 tclass = TREE_CODE_CLASS (TREE_CODE (node));
1906 if (tclass == tcc_declaration)
1908 if (DECL_NAME (node))
1909 pp_ada_tree_identifier
1910 (buffer, DECL_NAME (node), 0, limited_access);
1911 else
1912 pp_string (buffer, "<unnamed type decl>");
1914 else if (tclass == tcc_type)
1916 if (TYPE_NAME (node))
1918 if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
1919 pp_ada_tree_identifier (buffer, TYPE_NAME (node),
1920 node, limited_access);
1921 else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
1922 && DECL_NAME (TYPE_NAME (node)))
1923 dump_ada_decl_name (buffer, TYPE_NAME (node), limited_access);
1924 else
1925 pp_string (buffer, "<unnamed type>");
1927 else if (TREE_CODE (node) == INTEGER_TYPE)
1929 append_withs ("Interfaces.C.Extensions", false);
1930 bitfield_used = true;
1932 if (TYPE_PRECISION (node) == 1)
1933 pp_string (buffer, "Extensions.Unsigned_1");
1934 else
1936 pp_string (buffer, (TYPE_UNSIGNED (node)
1937 ? "Extensions.Unsigned_"
1938 : "Extensions.Signed_"));
1939 pp_decimal_int (buffer, TYPE_PRECISION (node));
1942 else
1943 pp_string (buffer, "<unnamed type>");
1945 break;
1948 case POINTER_TYPE:
1949 case REFERENCE_TYPE:
1950 if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
1952 tree fnode = TREE_TYPE (node);
1953 bool is_function;
1954 bool prev_in_function = in_function;
1956 if (VOID_TYPE_P (TREE_TYPE (fnode)))
1958 is_function = false;
1959 pp_string (buffer, "access procedure");
1961 else
1963 is_function = true;
1964 pp_string (buffer, "access function");
1967 in_function = is_function;
1968 dump_ada_function_declaration
1969 (buffer, node, false, false, false, spc + INDENT_INCR);
1970 in_function = prev_in_function;
1972 if (is_function)
1974 pp_string (buffer, " return ");
1975 dump_generic_ada_node
1976 (buffer, TREE_TYPE (fnode), type, cpp_check, spc, 0, true);
1979 else
1981 int is_access = false;
1982 unsigned int quals = TYPE_QUALS (TREE_TYPE (node));
1984 if (name_only && TYPE_NAME (node))
1985 dump_generic_ada_node
1986 (buffer, TYPE_NAME (node), node, cpp_check,
1987 spc, limited_access, true);
1988 else if (VOID_TYPE_P (TREE_TYPE (node)))
1990 if (!name_only)
1991 pp_string (buffer, "new ");
1992 if (package_prefix)
1994 append_withs ("System", false);
1995 pp_string (buffer, "System.Address");
1997 else
1998 pp_string (buffer, "address");
2000 else
2002 if (TREE_CODE (node) == POINTER_TYPE
2003 && TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE
2004 && !strcmp
2005 (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME
2006 (TREE_TYPE (node)))), "char"))
2008 if (!name_only)
2009 pp_string (buffer, "new ");
2011 if (package_prefix)
2013 pp_string (buffer, "Interfaces.C.Strings.chars_ptr");
2014 append_withs ("Interfaces.C.Strings", false);
2016 else
2017 pp_string (buffer, "chars_ptr");
2019 else
2021 /* For now, handle all access-to-access or
2022 access-to-unknown-structs as opaque system.address. */
2024 tree type_name = TYPE_NAME (TREE_TYPE (node));
2025 const_tree typ2 = !type ||
2026 DECL_P (type) ? type : TYPE_NAME (type);
2027 const_tree underlying_type =
2028 get_underlying_decl (TREE_TYPE (node));
2030 if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE
2031 /* Pointer to pointer. */
2033 || (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2034 && (!underlying_type
2035 || !TYPE_FIELDS (TREE_TYPE (underlying_type))))
2036 /* Pointer to opaque structure. */
2038 || underlying_type == NULL_TREE
2039 || (!typ2
2040 && !TREE_VISITED (underlying_type)
2041 && !TREE_VISITED (type_name)
2042 && !is_tagged_type (TREE_TYPE (node))
2043 && DECL_SOURCE_FILE (underlying_type)
2044 == source_file_base)
2045 || (type_name && typ2
2046 && DECL_P (underlying_type)
2047 && DECL_P (typ2)
2048 && decl_sloc (underlying_type, true)
2049 > decl_sloc (typ2, true)
2050 && DECL_SOURCE_FILE (underlying_type)
2051 == DECL_SOURCE_FILE (typ2)))
2053 if (package_prefix)
2055 append_withs ("System", false);
2056 if (!name_only)
2057 pp_string (buffer, "new ");
2058 pp_string (buffer, "System.Address");
2060 else
2061 pp_string (buffer, "address");
2062 return spc;
2065 if (!package_prefix)
2066 pp_string (buffer, "access");
2067 else if (AGGREGATE_TYPE_P (TREE_TYPE (node)))
2069 if (!type || TREE_CODE (type) != FUNCTION_DECL)
2071 pp_string (buffer, "access ");
2072 is_access = true;
2074 if (quals & TYPE_QUAL_CONST)
2075 pp_string (buffer, "constant ");
2076 else if (!name_only)
2077 pp_string (buffer, "all ");
2079 else if (quals & TYPE_QUAL_CONST)
2080 pp_string (buffer, "in ");
2081 else if (in_function)
2083 is_access = true;
2084 pp_string (buffer, "access ");
2086 else
2088 is_access = true;
2089 pp_string (buffer, "access ");
2090 /* ??? should be configurable: access or in out. */
2093 else
2095 is_access = true;
2096 pp_string (buffer, "access ");
2098 if (!name_only)
2099 pp_string (buffer, "all ");
2102 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2103 && type_name != NULL_TREE)
2104 dump_generic_ada_node
2105 (buffer, type_name,
2106 TREE_TYPE (node), cpp_check, spc, is_access, true);
2107 else
2108 dump_generic_ada_node
2109 (buffer, TREE_TYPE (node), TREE_TYPE (node),
2110 cpp_check, spc, 0, true);
2114 break;
2116 case ARRAY_TYPE:
2117 if (name_only)
2118 dump_generic_ada_node
2119 (buffer, TYPE_NAME (node), node, cpp_check,
2120 spc, limited_access, true);
2121 else
2122 dump_ada_array_type (buffer, node, spc);
2123 break;
2125 case RECORD_TYPE:
2126 case UNION_TYPE:
2127 case QUAL_UNION_TYPE:
2128 if (name_only)
2130 if (TYPE_NAME (node))
2131 dump_generic_ada_node
2132 (buffer, TYPE_NAME (node), node, cpp_check,
2133 spc, limited_access, true);
2134 else
2136 pp_string (buffer, "anon_");
2137 pp_scalar (buffer, "%d", TYPE_UID (node));
2140 else
2141 print_ada_struct_decl
2142 (buffer, node, type, cpp_check, spc, true);
2143 break;
2145 case INTEGER_CST:
2146 if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE)
2148 pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
2149 pp_string (buffer, "B"); /* pseudo-unit */
2151 else if (!host_integerp (node, 0))
2153 tree val = node;
2154 unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (val);
2155 HOST_WIDE_INT high = TREE_INT_CST_HIGH (val);
2157 if (tree_int_cst_sgn (val) < 0)
2159 pp_character (buffer, '-');
2160 high = ~high + !low;
2161 low = -low;
2163 sprintf (pp_buffer (buffer)->digit_buffer,
2164 HOST_WIDE_INT_PRINT_DOUBLE_HEX,
2165 (unsigned HOST_WIDE_INT) high, low);
2166 pp_string (buffer, pp_buffer (buffer)->digit_buffer);
2168 else
2169 pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
2170 break;
2172 case REAL_CST:
2173 case FIXED_CST:
2174 case COMPLEX_CST:
2175 case STRING_CST:
2176 case VECTOR_CST:
2177 return 0;
2179 case FUNCTION_DECL:
2180 case CONST_DECL:
2181 dump_ada_decl_name (buffer, node, limited_access);
2182 break;
2184 case TYPE_DECL:
2185 if (DECL_IS_BUILTIN (node))
2187 /* Don't print the declaration of built-in types. */
2189 if (name_only)
2191 /* If we're in the middle of a declaration, defaults to
2192 System.Address. */
2193 if (package_prefix)
2195 append_withs ("System", false);
2196 pp_string (buffer, "System.Address");
2198 else
2199 pp_string (buffer, "address");
2201 break;
2204 if (name_only)
2205 dump_ada_decl_name (buffer, node, limited_access);
2206 else
2208 if (is_tagged_type (TREE_TYPE (node)))
2210 tree tmp = TYPE_FIELDS (TREE_TYPE (node));
2211 int first = 1;
2213 /* Look for ancestors. */
2214 for (; tmp; tmp = TREE_CHAIN (tmp))
2216 if (!DECL_NAME (tmp) && is_tagged_type (TREE_TYPE (tmp)))
2218 if (first)
2220 pp_string (buffer, "limited new ");
2221 first = 0;
2223 else
2224 pp_string (buffer, " and ");
2226 dump_ada_decl_name
2227 (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
2231 pp_string (buffer, first ? "tagged limited " : " with ");
2233 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2234 && TYPE_METHODS (TREE_TYPE (node)))
2235 pp_string (buffer, "limited ");
2237 dump_generic_ada_node
2238 (buffer, TREE_TYPE (node), type, cpp_check, spc, false, false);
2240 break;
2242 case VAR_DECL:
2243 case PARM_DECL:
2244 case FIELD_DECL:
2245 case NAMESPACE_DECL:
2246 dump_ada_decl_name (buffer, node, false);
2247 break;
2249 default:
2250 /* Ignore other nodes (e.g. expressions). */
2251 return 0;
2254 return 1;
2257 /* Dump in BUFFER NODE's methods. CPP_CHECK is used to perform C++ queries on
2258 nodes. SPC is the indentation level. */
2260 static void
2261 print_ada_methods (pretty_printer *buffer, tree node,
2262 int (*cpp_check)(tree, cpp_operation), int spc)
2264 tree tmp = TYPE_METHODS (node);
2265 int res = 1;
2267 if (tmp)
2269 pp_semicolon (buffer);
2271 for (; tmp; tmp = TREE_CHAIN (tmp))
2273 if (res)
2275 pp_newline (buffer);
2276 pp_newline (buffer);
2278 res = print_ada_declaration (buffer, tmp, node, cpp_check, spc);
2283 /* Dump in BUFFER anonymous types nested inside T's definition.
2284 PARENT is the parent node of T.
2285 FORWARD indicates whether a forward declaration of T should be generated.
2286 CPP_CHECK is used to perform C++ queries on
2287 nodes. SPC is the indentation level. */
2289 static void
2290 dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
2291 int (*cpp_check)(tree, cpp_operation), int spc)
2293 tree field, outer, decl;
2295 /* Avoid recursing over the same tree. */
2296 if (TREE_VISITED (t))
2297 return;
2299 /* Find possible anonymous arrays/unions/structs recursively. */
2301 outer = TREE_TYPE (t);
2303 if (outer == NULL_TREE)
2304 return;
2306 if (forward)
2308 pp_string (buffer, "type ");
2309 dump_generic_ada_node
2310 (buffer, t, t, cpp_check, spc, false, true);
2311 pp_semicolon (buffer);
2312 newline_and_indent (buffer, spc);
2313 TREE_VISITED (t) = 1;
2316 field = TYPE_FIELDS (outer);
2317 while (field)
2319 if ((TREE_TYPE (field) != outer
2320 || (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2321 && TREE_TYPE (TREE_TYPE (field)) != outer))
2322 && (!TYPE_NAME (TREE_TYPE (field))
2323 || (TREE_CODE (field) == TYPE_DECL
2324 && DECL_NAME (field) != DECL_NAME (t)
2325 && TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (outer))))
2327 switch (TREE_CODE (TREE_TYPE (field)))
2329 case POINTER_TYPE:
2330 decl = TREE_TYPE (TREE_TYPE (field));
2332 if (TREE_CODE (decl) == FUNCTION_TYPE)
2333 for (decl = TREE_TYPE (decl);
2334 decl && TREE_CODE (decl) == POINTER_TYPE;
2335 decl = TREE_TYPE (decl));
2337 decl = get_underlying_decl (decl);
2339 if (decl
2340 && DECL_P (decl)
2341 && decl_sloc (decl, true) > decl_sloc (t, true)
2342 && DECL_SOURCE_FILE (decl) == DECL_SOURCE_FILE (t)
2343 && !TREE_VISITED (decl)
2344 && !DECL_IS_BUILTIN (decl)
2345 && (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
2346 || TYPE_FIELDS (TREE_TYPE (decl))))
2348 /* Generate forward declaration. */
2350 pp_string (buffer, "type ");
2351 dump_generic_ada_node
2352 (buffer, decl, 0, cpp_check, spc, false, true);
2353 pp_semicolon (buffer);
2354 newline_and_indent (buffer, spc);
2356 /* Ensure we do not generate duplicate forward
2357 declarations for this type. */
2358 TREE_VISITED (decl) = 1;
2360 break;
2362 case ARRAY_TYPE:
2363 /* Special case char arrays. */
2364 if (is_char_array (field))
2365 pp_string (buffer, "sub");
2367 pp_string (buffer, "type ");
2368 dump_ada_double_name (buffer, parent, field, "_array is ");
2369 dump_ada_array_type (buffer, field, spc);
2370 pp_semicolon (buffer);
2371 newline_and_indent (buffer, spc);
2372 break;
2374 case UNION_TYPE:
2375 TREE_VISITED (t) = 1;
2376 dump_nested_types (buffer, field, t, false, cpp_check, spc);
2378 pp_string (buffer, "type ");
2380 if (TYPE_NAME (TREE_TYPE (field)))
2382 dump_generic_ada_node
2383 (buffer, TYPE_NAME (TREE_TYPE (field)), 0, cpp_check,
2384 spc, false, true);
2385 pp_string (buffer, " (discr : unsigned := 0) is ");
2386 print_ada_struct_decl
2387 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2389 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2390 dump_generic_ada_node
2391 (buffer, TREE_TYPE (field), 0, cpp_check,
2392 spc, false, true);
2393 pp_string (buffer, ");");
2394 newline_and_indent (buffer, spc);
2396 pp_string (buffer, "pragma Unchecked_Union (");
2397 dump_generic_ada_node
2398 (buffer, TREE_TYPE (field), 0, cpp_check,
2399 spc, false, true);
2400 pp_string (buffer, ");");
2402 else
2404 dump_ada_double_name
2405 (buffer, parent, field,
2406 "_union (discr : unsigned := 0) is ");
2407 print_ada_struct_decl
2408 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2409 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2410 dump_ada_double_name (buffer, parent, field, "_union);");
2411 newline_and_indent (buffer, spc);
2413 pp_string (buffer, "pragma Unchecked_Union (");
2414 dump_ada_double_name (buffer, parent, field, "_union);");
2417 newline_and_indent (buffer, spc);
2418 break;
2420 case RECORD_TYPE:
2421 if (TYPE_NAME (TREE_TYPE (t)) && !TREE_VISITED (t))
2423 pp_string (buffer, "type ");
2424 dump_generic_ada_node
2425 (buffer, t, parent, 0, spc, false, true);
2426 pp_semicolon (buffer);
2427 newline_and_indent (buffer, spc);
2430 TREE_VISITED (t) = 1;
2431 dump_nested_types (buffer, field, t, false, cpp_check, spc);
2432 pp_string (buffer, "type ");
2434 if (TYPE_NAME (TREE_TYPE (field)))
2436 dump_generic_ada_node
2437 (buffer, TREE_TYPE (field), 0, cpp_check,
2438 spc, false, true);
2439 pp_string (buffer, " is ");
2440 print_ada_struct_decl
2441 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2442 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2443 dump_generic_ada_node
2444 (buffer, TREE_TYPE (field), 0, cpp_check,
2445 spc, false, true);
2446 pp_string (buffer, ");");
2448 else
2450 dump_ada_double_name
2451 (buffer, parent, field, "_struct is ");
2452 print_ada_struct_decl
2453 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2454 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2455 dump_ada_double_name (buffer, parent, field, "_struct);");
2458 newline_and_indent (buffer, spc);
2459 break;
2461 default:
2462 break;
2465 field = TREE_CHAIN (field);
2468 TREE_VISITED (t) = 1;
2471 /* Dump in BUFFER destructor spec corresponding to T. */
2473 static void
2474 print_destructor (pretty_printer *buffer, tree t)
2476 const char *s = IDENTIFIER_POINTER (DECL_NAME (t));
2478 if (*s == '_')
2479 for (s += 2; *s != ' '; s++)
2480 pp_character (buffer, *s);
2481 else
2483 pp_string (buffer, "Delete_");
2484 pp_ada_tree_identifier (buffer, DECL_NAME (t), t, false);
2488 /* Return the name of type T. */
2490 static const char *
2491 type_name (tree t)
2493 tree n = TYPE_NAME (t);
2495 if (TREE_CODE (n) == IDENTIFIER_NODE)
2496 return IDENTIFIER_POINTER (n);
2497 else
2498 return IDENTIFIER_POINTER (DECL_NAME (n));
2501 /* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
2502 CPP_CHECK is used to perform C++ queries on nodes. SPC is the indentation
2503 level. Return 1 if a declaration was printed, 0 otherwise. */
2505 static int
2506 print_ada_declaration (pretty_printer *buffer, tree t, tree type,
2507 int (*cpp_check)(tree, cpp_operation), int spc)
2509 int is_var = 0, need_indent = 0;
2510 int is_class = false;
2511 tree name = TYPE_NAME (TREE_TYPE (t));
2512 tree decl_name = DECL_NAME (t);
2513 bool dump_internal = get_dump_file_info (TDI_ada)->flags & TDF_RAW;
2514 tree orig = NULL_TREE;
2516 if (cpp_check && cpp_check (t, IS_TEMPLATE))
2517 return dump_ada_template (buffer, t, cpp_check, spc);
2519 if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
2520 /* Skip enumeral values: will be handled as part of the type itself. */
2521 return 0;
2523 if (TREE_CODE (t) == TYPE_DECL)
2525 orig = DECL_ORIGINAL_TYPE (t);
2527 if (orig && TYPE_STUB_DECL (orig))
2529 tree stub = TYPE_STUB_DECL (orig);
2530 tree typ = TREE_TYPE (stub);
2532 if (TYPE_NAME (typ))
2534 /* If types have same representation, and same name (ignoring
2535 casing), then ignore the second type. */
2536 if (type_name (typ) == type_name (TREE_TYPE (t))
2537 || !strcasecmp (type_name (typ), type_name (TREE_TYPE (t))))
2538 return 0;
2540 INDENT (spc);
2542 if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
2544 pp_string (buffer, "-- skipped empty struct ");
2545 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2547 else
2549 if (!TREE_VISITED (stub)
2550 && DECL_SOURCE_FILE (stub) == source_file_base)
2551 dump_nested_types
2552 (buffer, stub, stub, true, cpp_check, spc);
2554 pp_string (buffer, "subtype ");
2555 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2556 pp_string (buffer, " is ");
2557 dump_generic_ada_node
2558 (buffer, typ, type, 0, spc, false, true);
2559 pp_semicolon (buffer);
2561 return 1;
2565 /* Skip unnamed or anonymous structs/unions/enum types. */
2566 if (!orig && !decl_name && !name)
2568 tree tmp;
2569 location_t sloc;
2571 if (cpp_check || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
2572 return 0;
2574 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
2576 /* Search next items until finding a named type decl. */
2577 sloc = decl_sloc_common (t, true, true);
2579 for (tmp = TREE_CHAIN (t); tmp; tmp = TREE_CHAIN (tmp))
2581 if (TREE_CODE (tmp) == TYPE_DECL
2582 && (DECL_NAME (tmp) || TYPE_NAME (TREE_TYPE (tmp))))
2584 /* If same sloc, it means we can ignore the anonymous
2585 struct. */
2586 if (decl_sloc_common (tmp, true, true) == sloc)
2587 return 0;
2588 else
2589 break;
2592 if (tmp == NULL)
2593 return 0;
2597 if (!orig
2598 && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE
2599 && decl_name
2600 && (*IDENTIFIER_POINTER (decl_name) == '.'
2601 || *IDENTIFIER_POINTER (decl_name) == '$'))
2602 /* Skip anonymous enum types (duplicates of real types). */
2603 return 0;
2605 INDENT (spc);
2607 switch (TREE_CODE (TREE_TYPE (t)))
2609 case RECORD_TYPE:
2610 case UNION_TYPE:
2611 case QUAL_UNION_TYPE:
2612 /* Skip empty structs (typically forward references to real
2613 structs). */
2614 if (!TYPE_FIELDS (TREE_TYPE (t)))
2616 pp_string (buffer, "-- skipped empty struct ");
2617 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2618 return 1;
2621 if (decl_name
2622 && (*IDENTIFIER_POINTER (decl_name) == '.'
2623 || *IDENTIFIER_POINTER (decl_name) == '$'))
2625 pp_string (buffer, "-- skipped anonymous struct ");
2626 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2627 TREE_VISITED (t) = 1;
2628 return 1;
2631 if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2632 pp_string (buffer, "subtype ");
2633 else
2635 dump_nested_types (buffer, t, t, false, cpp_check, spc);
2637 if (separate_class_package (t))
2639 is_class = true;
2640 pp_string (buffer, "package Class_");
2641 dump_generic_ada_node
2642 (buffer, t, type, 0, spc, false, true);
2643 pp_string (buffer, " is");
2644 spc += INDENT_INCR;
2645 newline_and_indent (buffer, spc);
2648 pp_string (buffer, "type ");
2650 break;
2652 case ARRAY_TYPE:
2653 case POINTER_TYPE:
2654 case REFERENCE_TYPE:
2655 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2656 || is_char_array (t))
2657 pp_string (buffer, "subtype ");
2658 else
2659 pp_string (buffer, "type ");
2660 break;
2662 case FUNCTION_TYPE:
2663 pp_string (buffer, "-- skipped function type ");
2664 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2665 return 1;
2666 break;
2668 case ENUMERAL_TYPE:
2669 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2670 || !is_simple_enum (TREE_TYPE (t)))
2671 pp_string (buffer, "subtype ");
2672 else
2673 pp_string (buffer, "type ");
2674 break;
2676 default:
2677 pp_string (buffer, "subtype ");
2679 TREE_VISITED (t) = 1;
2681 else
2683 if (!dump_internal
2684 && TREE_CODE (t) == VAR_DECL
2685 && decl_name
2686 && *IDENTIFIER_POINTER (decl_name) == '_')
2687 return 0;
2689 need_indent = 1;
2692 /* Print the type and name. */
2693 if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
2695 if (need_indent)
2696 INDENT (spc);
2698 /* Print variable's name. */
2699 dump_generic_ada_node (buffer, t, type, cpp_check, spc, false, true);
2701 if (TREE_CODE (t) == TYPE_DECL)
2703 pp_string (buffer, " is ");
2705 if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2706 dump_generic_ada_node
2707 (buffer, TYPE_NAME (orig), type,
2708 cpp_check, spc, false, true);
2709 else
2710 dump_ada_array_type (buffer, t, spc);
2712 else
2714 tree tmp = TYPE_NAME (TREE_TYPE (t));
2716 if (spc == INDENT_INCR || TREE_STATIC (t))
2717 is_var = 1;
2719 pp_string (buffer, " : ");
2721 if (tmp)
2723 if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE
2724 && TREE_CODE (tmp) != INTEGER_TYPE)
2725 pp_string (buffer, "aliased ");
2727 dump_generic_ada_node (buffer, tmp, type, 0, spc, false, true);
2729 else
2731 pp_string (buffer, "aliased ");
2733 if (!type)
2734 dump_ada_array_type (buffer, t, spc);
2735 else
2736 dump_ada_double_name (buffer, type, t, "_array");
2740 else if (TREE_CODE (t) == FUNCTION_DECL)
2742 bool is_function = true, is_method, is_abstract_class = false;
2743 tree decl_name = DECL_NAME (t);
2744 int prev_in_function = in_function;
2745 bool is_abstract = false;
2746 bool is_constructor = false;
2747 bool is_destructor = false;
2748 bool is_copy_constructor = false;
2750 if (!decl_name)
2751 return 0;
2753 if (cpp_check)
2755 is_abstract = cpp_check (t, IS_ABSTRACT);
2756 is_constructor = cpp_check (t, IS_CONSTRUCTOR);
2757 is_destructor = cpp_check (t, IS_DESTRUCTOR);
2758 is_copy_constructor = cpp_check (t, IS_COPY_CONSTRUCTOR);
2761 /* Skip __comp_dtor destructor which is redundant with the '~class()'
2762 destructor. */
2763 if (is_destructor
2764 && !strncmp (IDENTIFIER_POINTER (decl_name), "__comp", 6))
2765 return 0;
2767 /* Skip copy constructors: some are internal only, and those that are
2768 not cannot be called easily from Ada anyway. */
2769 if (is_copy_constructor)
2770 return 0;
2772 /* If this function has an entry in the dispatch table, we cannot
2773 omit it. */
2774 if (!dump_internal && !DECL_VINDEX (t)
2775 && *IDENTIFIER_POINTER (decl_name) == '_')
2777 if (IDENTIFIER_POINTER (decl_name)[1] == '_')
2778 return 0;
2780 INDENT (spc);
2781 pp_string (buffer, "-- skipped func ");
2782 pp_string (buffer, IDENTIFIER_POINTER (decl_name));
2783 return 1;
2786 if (need_indent)
2787 INDENT (spc);
2789 if (is_constructor)
2790 pp_string (buffer, "function New_");
2791 else if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
2793 is_function = false;
2794 pp_string (buffer, "procedure ");
2796 else
2797 pp_string (buffer, "function ");
2799 in_function = is_function;
2800 is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
2802 if (is_destructor)
2803 print_destructor (buffer, t);
2804 else
2805 dump_ada_decl_name (buffer, t, false);
2807 dump_ada_function_declaration
2808 (buffer, t, is_method, is_constructor, is_destructor, spc);
2809 in_function = prev_in_function;
2811 if (is_function)
2813 pp_string (buffer, " return ");
2815 if (is_constructor)
2817 dump_ada_decl_name (buffer, t, false);
2819 else
2821 dump_generic_ada_node
2822 (buffer, TREE_TYPE (TREE_TYPE (t)), type, cpp_check,
2823 spc, false, true);
2827 if (is_constructor && cpp_check && type
2828 && AGGREGATE_TYPE_P (type)
2829 && TYPE_METHODS (type))
2831 tree tmp = TYPE_METHODS (type);
2833 for (; tmp; tmp = TREE_CHAIN (tmp))
2834 if (cpp_check (tmp, IS_ABSTRACT))
2836 is_abstract_class = 1;
2837 break;
2841 if (is_abstract || is_abstract_class)
2842 pp_string (buffer, " is abstract");
2844 pp_semicolon (buffer);
2845 pp_string (buffer, " -- ");
2846 dump_sloc (buffer, t);
2848 if (is_abstract)
2849 return 1;
2851 newline_and_indent (buffer, spc);
2853 if (is_constructor)
2855 pp_string (buffer, "pragma CPP_Constructor (New_");
2856 dump_ada_decl_name (buffer, t, false);
2857 pp_string (buffer, ", \"");
2858 pp_asm_name (buffer, t);
2859 pp_string (buffer, "\");");
2861 else if (is_destructor)
2863 pp_string (buffer, "pragma Import (CPP, ");
2864 print_destructor (buffer, t);
2865 pp_string (buffer, ", \"");
2866 pp_asm_name (buffer, t);
2867 pp_string (buffer, "\");");
2869 else
2871 dump_ada_import (buffer, t);
2874 return 1;
2876 else if (TREE_CODE (t) == TYPE_DECL && !DECL_ORIGINAL_TYPE (t))
2878 int is_interface = 0;
2879 int is_abstract_record = 0;
2881 if (need_indent)
2882 INDENT (spc);
2884 /* Anonymous structs/unions */
2885 dump_generic_ada_node
2886 (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
2888 if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
2889 || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE)
2891 pp_string (buffer, " (discr : unsigned := 0)");
2894 pp_string (buffer, " is ");
2896 /* Check whether we have an Ada interface compatible class. */
2897 if (cpp_check && AGGREGATE_TYPE_P (TREE_TYPE (t))
2898 && TYPE_METHODS (TREE_TYPE (t)))
2900 int num_fields = 0;
2901 tree tmp = TYPE_FIELDS (TREE_TYPE (t));
2903 /* Check that there are no fields other than the virtual table. */
2904 for (; tmp; tmp = TREE_CHAIN (tmp))
2906 if (TREE_CODE (tmp) == TYPE_DECL)
2907 continue;
2908 num_fields++;
2911 if (num_fields == 1)
2912 is_interface = 1;
2914 /* Also check that there are only virtual methods. */
2915 for (tmp = TYPE_METHODS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
2917 if (cpp_check (tmp, IS_ABSTRACT))
2918 is_abstract_record = 1;
2919 else
2920 is_interface = 0;
2924 TREE_VISITED (t) = 1;
2925 if (is_interface)
2927 pp_string (buffer, "limited interface; -- ");
2928 dump_sloc (buffer, t);
2929 newline_and_indent (buffer, spc);
2930 pp_string (buffer, "pragma Import (CPP, ");
2931 dump_generic_ada_node
2932 (buffer, TYPE_NAME (TREE_TYPE (t)), type, cpp_check,
2933 spc, false, true);
2934 pp_character (buffer, ')');
2936 print_ada_methods (buffer, TREE_TYPE (t), cpp_check, spc);
2938 else
2940 if (is_abstract_record)
2941 pp_string (buffer, "abstract ");
2942 dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, false);
2945 else
2947 if (need_indent)
2948 INDENT (spc);
2950 if (TREE_CODE (t) == FIELD_DECL && DECL_NAME (t))
2951 check_name (buffer, t);
2953 /* Print variable/type's name. */
2954 dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, true);
2956 if (TREE_CODE (t) == TYPE_DECL)
2958 tree orig = DECL_ORIGINAL_TYPE (t);
2959 int is_subtype = orig && TYPE_NAME (orig) && orig != TREE_TYPE (t);
2961 if (!is_subtype
2962 && (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
2963 || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE))
2964 pp_string (buffer, " (discr : unsigned := 0)");
2966 pp_string (buffer, " is ");
2968 dump_generic_ada_node
2969 (buffer, orig, t, cpp_check, spc, false, is_subtype);
2971 else
2973 if (spc == INDENT_INCR || TREE_STATIC (t))
2974 is_var = 1;
2976 pp_string (buffer, " : ");
2978 /* Print type declaration. */
2980 if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
2981 && !TYPE_NAME (TREE_TYPE (t)))
2983 dump_ada_double_name (buffer, type, t, "_union");
2985 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
2987 if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
2988 pp_string (buffer, "aliased ");
2990 dump_generic_ada_node
2991 (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
2993 else
2995 if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
2996 && (TYPE_NAME (TREE_TYPE (t))
2997 || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE))
2998 pp_string (buffer, "aliased ");
3000 dump_generic_ada_node
3001 (buffer, TREE_TYPE (t), TREE_TYPE (t), cpp_check,
3002 spc, false, true);
3007 if (is_class)
3009 spc -= 3;
3010 newline_and_indent (buffer, spc);
3011 pp_string (buffer, "end;");
3012 newline_and_indent (buffer, spc);
3013 pp_string (buffer, "use Class_");
3014 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
3015 pp_semicolon (buffer);
3016 pp_newline (buffer);
3018 /* All needed indentation/newline performed already, so return 0. */
3019 return 0;
3021 else
3023 pp_string (buffer, "; -- ");
3024 dump_sloc (buffer, t);
3027 if (is_var)
3029 newline_and_indent (buffer, spc);
3030 dump_ada_import (buffer, t);
3033 return 1;
3036 /* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
3037 with Ada syntax. CPP_CHECK is used to perform C++ queries on nodes. SPC
3038 is the indentation level. If DISPLAY_CONVENTION is true, also print the
3039 pragma Convention for NODE. */
3041 static void
3042 print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
3043 int (*cpp_check)(tree, cpp_operation), int spc,
3044 bool display_convention)
3046 tree tmp;
3047 int is_union =
3048 TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
3049 char buf [16];
3050 int field_num = 0;
3051 int field_spc = spc + INDENT_INCR;
3052 int need_semicolon;
3054 bitfield_used = false;
3056 if (!TYPE_FIELDS (node))
3057 pp_string (buffer, "null record;");
3058 else
3060 pp_string (buffer, "record");
3062 /* Print the contents of the structure. */
3064 if (is_union)
3066 newline_and_indent (buffer, spc + INDENT_INCR);
3067 pp_string (buffer, "case discr is");
3068 field_spc = spc + INDENT_INCR * 3;
3071 pp_newline (buffer);
3073 /* Print the non-static fields of the structure. */
3074 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3076 /* Add parent field if needed. */
3077 if (!DECL_NAME (tmp))
3079 if (!is_tagged_type (TREE_TYPE (tmp)))
3081 if (!TYPE_NAME (TREE_TYPE (tmp)))
3082 print_ada_declaration
3083 (buffer, tmp, type, cpp_check, field_spc);
3084 else
3086 INDENT (field_spc);
3088 if (field_num == 0)
3089 pp_string (buffer, "parent : ");
3090 else
3092 sprintf (buf, "field_%d : ", field_num + 1);
3093 pp_string (buffer, buf);
3095 dump_ada_decl_name
3096 (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
3097 pp_semicolon (buffer);
3099 pp_newline (buffer);
3100 field_num++;
3103 /* Avoid printing the structure recursively. */
3104 else if ((TREE_TYPE (tmp) != node
3105 || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
3106 && TREE_TYPE (TREE_TYPE (tmp)) != node))
3107 && TREE_CODE (tmp) != TYPE_DECL
3108 && !TREE_STATIC (tmp))
3110 /* Skip internal virtual table field. */
3111 if (strncmp (IDENTIFIER_POINTER (DECL_NAME (tmp)), "_vptr", 5))
3113 if (is_union)
3115 if (TREE_CHAIN (tmp)
3116 && TREE_TYPE (TREE_CHAIN (tmp)) != node
3117 && TREE_CODE (TREE_CHAIN (tmp)) != TYPE_DECL)
3118 sprintf (buf, "when %d =>", field_num);
3119 else
3120 sprintf (buf, "when others =>");
3122 INDENT (spc + INDENT_INCR * 2);
3123 pp_string (buffer, buf);
3124 pp_newline (buffer);
3127 if (print_ada_declaration (buffer,
3128 tmp, type, cpp_check, field_spc))
3130 pp_newline (buffer);
3131 field_num++;
3137 if (is_union)
3139 INDENT (spc + INDENT_INCR);
3140 pp_string (buffer, "end case;");
3141 pp_newline (buffer);
3144 if (field_num == 0)
3146 INDENT (spc + INDENT_INCR);
3147 pp_string (buffer, "null;");
3148 pp_newline (buffer);
3151 INDENT (spc);
3152 pp_string (buffer, "end record;");
3155 newline_and_indent (buffer, spc);
3157 if (!display_convention)
3158 return;
3160 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
3162 if (TYPE_METHODS (TREE_TYPE (type)))
3163 pp_string (buffer, "pragma Import (CPP, ");
3164 else
3165 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
3167 else
3168 pp_string (buffer, "pragma Convention (C, ");
3170 package_prefix = false;
3171 dump_generic_ada_node
3172 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3173 package_prefix = true;
3174 pp_character (buffer, ')');
3176 if (is_union)
3178 pp_semicolon (buffer);
3179 newline_and_indent (buffer, spc);
3180 pp_string (buffer, "pragma Unchecked_Union (");
3182 dump_generic_ada_node
3183 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3184 pp_character (buffer, ')');
3187 if (bitfield_used)
3189 pp_semicolon (buffer);
3190 newline_and_indent (buffer, spc);
3191 pp_string (buffer, "pragma Pack (");
3192 dump_generic_ada_node
3193 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3194 pp_character (buffer, ')');
3195 bitfield_used = false;
3198 print_ada_methods (buffer, node, cpp_check, spc);
3200 /* Print the static fields of the structure, if any. */
3201 need_semicolon = TYPE_METHODS (node) == NULL_TREE;
3202 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3204 if (DECL_NAME (tmp) && TREE_STATIC (tmp))
3206 if (need_semicolon)
3208 need_semicolon = false;
3209 pp_semicolon (buffer);
3211 pp_newline (buffer);
3212 pp_newline (buffer);
3213 print_ada_declaration (buffer, tmp, type, cpp_check, spc);
3218 /* Dump all the declarations in SOURCE_FILE to an Ada spec.
3219 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3220 nodes for SOURCE_FILE. CPP_CHECK is used to perform C++ queries on
3221 nodes. */
3223 static void
3224 dump_ads (const char *source_file,
3225 void (*collect_all_refs)(const char *),
3226 int (*cpp_check)(tree, cpp_operation))
3228 char *ads_name;
3229 char *pkg_name;
3230 char *s;
3231 FILE *f;
3233 pkg_name = get_ada_package (source_file);
3235 /* Construct the the .ads filename and package name. */
3236 ads_name = xstrdup (pkg_name);
3238 for (s = ads_name; *s; s++)
3239 *s = TOLOWER (*s);
3241 ads_name = reconcat (ads_name, ads_name, ".ads", NULL);
3243 /* Write out the .ads file. */
3244 f = fopen (ads_name, "w");
3245 if (f)
3247 pretty_printer pp;
3249 pp_construct (&pp, NULL, 0);
3250 pp_needs_newline (&pp) = true;
3251 pp.buffer->stream = f;
3253 /* Dump all relevant macros. */
3254 dump_ada_macros (&pp, source_file);
3256 /* Reset the table of withs for this file. */
3257 reset_ada_withs ();
3259 (*collect_all_refs) (source_file);
3261 /* Dump all references. */
3262 dump_ada_nodes (&pp, source_file, cpp_check);
3264 /* Dump withs. */
3265 dump_ada_withs (f);
3267 fprintf (f, "\npackage %s is\n\n", pkg_name);
3268 pp_write_text_to_stream (&pp);
3269 /* ??? need to free pp */
3270 fprintf (f, "end %s;\n", pkg_name);
3271 fclose (f);
3274 free (ads_name);
3275 free (pkg_name);
3278 static const char **source_refs = NULL;
3279 static int source_refs_used = 0;
3280 static int source_refs_allocd = 0;
3282 /* Add an entry for FILENAME to the table SOURCE_REFS. */
3284 void
3285 collect_source_ref (const char *filename)
3287 int i;
3289 if (!filename)
3290 return;
3292 if (source_refs_allocd == 0)
3294 source_refs_allocd = 1024;
3295 source_refs = XNEWVEC (const char *, source_refs_allocd);
3298 for (i = 0; i < source_refs_used; i++)
3299 if (filename == source_refs [i])
3300 return;
3302 if (source_refs_used == source_refs_allocd)
3304 source_refs_allocd *= 2;
3305 source_refs = XRESIZEVEC (const char *, source_refs, source_refs_allocd);
3308 source_refs [source_refs_used++] = filename;
3311 /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
3312 using callbacks COLLECT_ALL_REFS and CPP_CHECK.
3313 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3314 nodes for a given source file.
3315 CPP_CHECK is used to perform C++ queries on nodes, or NULL for the C
3316 front-end. */
3318 void
3319 dump_ada_specs (void (*collect_all_refs)(const char *),
3320 int (*cpp_check)(tree, cpp_operation))
3322 int i;
3324 /* Iterate over the list of files to dump specs for */
3325 for (i = 0; i < source_refs_used; i++)
3326 dump_ads (source_refs [i], collect_all_refs, cpp_check);
3328 /* Free files table. */
3329 free (source_refs);