PR middle-end/48973
[official-gcc.git] / gcc / c-family / c-ada-spec.c
blobf582e7dfb0e391b534fc6215b1200292208a4504
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 filename_cmp (LOCATION_FILE (lhs->sloc),
563 LOCATION_FILE (rhs->sloc));
565 if (LOCATION_LINE (lhs->sloc) != LOCATION_LINE (rhs->sloc))
566 return LOCATION_LINE (lhs->sloc) - LOCATION_LINE (rhs->sloc);
568 if (LOCATION_COL (lhs->sloc) != LOCATION_COL (rhs->sloc))
569 return LOCATION_COL (lhs->sloc) - LOCATION_COL (rhs->sloc);
571 return 0;
574 static tree *to_dump = NULL;
575 static int to_dump_count = 0;
577 /* Collect a list of declarations from T relevant to SOURCE_FILE to be dumped
578 by a subsequent call to dump_ada_nodes. */
580 void
581 collect_ada_nodes (tree t, const char *source_file)
583 tree n;
584 int i = to_dump_count;
586 /* Count the likely relevant nodes. */
587 for (n = t; n; n = TREE_CHAIN (n))
588 if (!DECL_IS_BUILTIN (n)
589 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
590 to_dump_count++;
592 /* Allocate sufficient storage for all nodes. */
593 to_dump = XRESIZEVEC (tree, to_dump, to_dump_count);
595 /* Store the relevant nodes. */
596 for (n = t; n; n = TREE_CHAIN (n))
597 if (!DECL_IS_BUILTIN (n)
598 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
599 to_dump [i++] = n;
602 /* Call back for walk_tree to clear the TREE_VISITED flag of TP. */
604 static tree
605 unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
606 void *data ATTRIBUTE_UNUSED)
608 if (TREE_VISITED (*tp))
609 TREE_VISITED (*tp) = 0;
610 else
611 *walk_subtrees = 0;
613 return NULL_TREE;
616 /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
617 to collect_ada_nodes. CPP_CHECK is used to perform C++ queries on nodes. */
619 static void
620 dump_ada_nodes (pretty_printer *pp, const char *source_file,
621 int (*cpp_check)(tree, cpp_operation))
623 int i, j;
624 cpp_comment_table *comments;
626 /* Sort the table of declarations to dump by sloc. */
627 qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
629 /* Fetch the table of comments. */
630 comments = cpp_get_comments (parse_in);
632 /* Sort the comments table by sloc. */
633 qsort (comments->entries, comments->count, sizeof (cpp_comment),
634 compare_comment);
636 /* Interleave comments and declarations in line number order. */
637 i = j = 0;
640 /* Advance j until comment j is in this file. */
641 while (j != comments->count
642 && LOCATION_FILE (comments->entries[j].sloc) != source_file)
643 j++;
645 /* Advance j until comment j is not a duplicate. */
646 while (j < comments->count - 1
647 && !compare_comment (&comments->entries[j],
648 &comments->entries[j + 1]))
649 j++;
651 /* Write decls until decl i collates after comment j. */
652 while (i != to_dump_count)
654 if (j == comments->count
655 || LOCATION_LINE (decl_sloc (to_dump[i], false))
656 < LOCATION_LINE (comments->entries[j].sloc))
657 print_generic_ada_decl (pp, to_dump[i++], cpp_check, source_file);
658 else
659 break;
662 /* Write comment j, if there is one. */
663 if (j != comments->count)
664 print_comment (pp, comments->entries[j++].comment);
666 } while (i != to_dump_count || j != comments->count);
668 /* Clear the TREE_VISITED flag over each subtree we've dumped. */
669 for (i = 0; i < to_dump_count; i++)
670 walk_tree (&to_dump[i], unmark_visited_r, NULL, NULL);
672 /* Finalize the to_dump table. */
673 if (to_dump)
675 free (to_dump);
676 to_dump = NULL;
677 to_dump_count = 0;
681 /* Print a COMMENT to the output stream PP. */
683 static void
684 print_comment (pretty_printer *pp, const char *comment)
686 int len = strlen (comment);
687 char *str = XALLOCAVEC (char, len + 1);
688 char *tok;
689 bool extra_newline = false;
691 memcpy (str, comment, len + 1);
693 /* Trim C/C++ comment indicators. */
694 if (str[len - 2] == '*' && str[len - 1] == '/')
696 str[len - 2] = ' ';
697 str[len - 1] = '\0';
699 str += 2;
701 tok = strtok (str, "\n");
702 while (tok) {
703 pp_string (pp, " --");
704 pp_string (pp, tok);
705 pp_newline (pp);
706 tok = strtok (NULL, "\n");
708 /* Leave a blank line after multi-line comments. */
709 if (tok)
710 extra_newline = true;
713 if (extra_newline)
714 pp_newline (pp);
717 /* Prints declaration DECL to PP in Ada syntax. The current source file being
718 handled is SOURCE_FILE, and CPP_CHECK is used to perform C++ queries on
719 nodes. */
721 static void
722 print_generic_ada_decl (pretty_printer *pp, tree decl,
723 int (*cpp_check)(tree, cpp_operation),
724 const char* source_file)
726 source_file_base = source_file;
728 if (print_ada_declaration (pp, decl, 0, cpp_check, INDENT_INCR))
730 pp_newline (pp);
731 pp_newline (pp);
735 /* Dump a newline and indent BUFFER by SPC chars. */
737 static void
738 newline_and_indent (pretty_printer *buffer, int spc)
740 pp_newline (buffer);
741 INDENT (spc);
744 struct with { char *s; const char *in_file; int limited; };
745 static struct with *withs = NULL;
746 static int withs_max = 4096;
747 static int with_len = 0;
749 /* Record a "with" clause on package S (a limited with if LIMITED_ACCESS is
750 true), if not already done. */
752 static void
753 append_withs (const char *s, int limited_access)
755 int i;
757 if (withs == NULL)
758 withs = XNEWVEC (struct with, withs_max);
760 if (with_len == withs_max)
762 withs_max *= 2;
763 withs = XRESIZEVEC (struct with, withs, withs_max);
766 for (i = 0; i < with_len; i++)
767 if (!strcmp (s, withs [i].s)
768 && source_file_base == withs [i].in_file)
770 withs [i].limited &= limited_access;
771 return;
774 withs [with_len].s = xstrdup (s);
775 withs [with_len].in_file = source_file_base;
776 withs [with_len].limited = limited_access;
777 with_len++;
780 /* Reset "with" clauses. */
782 static void
783 reset_ada_withs (void)
785 int i;
787 if (!withs)
788 return;
790 for (i = 0; i < with_len; i++)
791 free (withs [i].s);
792 free (withs);
793 withs = NULL;
794 withs_max = 4096;
795 with_len = 0;
798 /* Dump "with" clauses in F. */
800 static void
801 dump_ada_withs (FILE *f)
803 int i;
805 fprintf (f, "with Interfaces.C; use Interfaces.C;\n");
807 for (i = 0; i < with_len; i++)
808 fprintf
809 (f, "%swith %s;\n", withs [i].limited ? "limited " : "", withs [i].s);
812 /* Return suitable Ada package name from FILE. */
814 static char *
815 get_ada_package (const char *file)
817 const char *base;
818 char *res;
819 const char *s;
820 int i;
822 s = strstr (file, "/include/");
823 if (s)
824 base = s + 9;
825 else
826 base = lbasename (file);
827 res = XNEWVEC (char, strlen (base) + 1);
829 for (i = 0; *base; base++, i++)
830 switch (*base)
832 case '+':
833 res [i] = 'p';
834 break;
836 case '.':
837 case '-':
838 case '_':
839 case '/':
840 case '\\':
841 res [i] = (i == 0 || res [i - 1] == '_') ? 'u' : '_';
842 break;
844 default:
845 res [i] = *base;
846 break;
848 res [i] = '\0';
850 return res;
853 static const char *ada_reserved[] = {
854 "abort", "abs", "abstract", "accept", "access", "aliased", "all", "and",
855 "array", "at", "begin", "body", "case", "constant", "declare", "delay",
856 "delta", "digits", "do", "else", "elsif", "end", "entry", "exception",
857 "exit", "for", "function", "generic", "goto", "if", "in", "interface", "is",
858 "limited", "loop", "mod", "new", "not", "null", "others", "out", "of", "or",
859 "overriding", "package", "pragma", "private", "procedure", "protected",
860 "raise", "range", "record", "rem", "renames", "requeue", "return", "reverse",
861 "select", "separate", "subtype", "synchronized", "tagged", "task",
862 "terminate", "then", "type", "until", "use", "when", "while", "with", "xor",
863 NULL};
865 /* ??? would be nice to specify this list via a config file, so that users
866 can create their own dictionary of conflicts. */
867 static const char *c_duplicates[] = {
868 /* system will cause troubles with System.Address. */
869 "system",
871 /* The following values have other definitions with same name/other
872 casing. */
873 "funmap",
874 "rl_vi_fWord",
875 "rl_vi_bWord",
876 "rl_vi_eWord",
877 "rl_readline_version",
878 "_Vx_ushort",
879 "USHORT",
880 "XLookupKeysym",
881 NULL};
883 /* Return a declaration tree corresponding to TYPE. */
885 static tree
886 get_underlying_decl (tree type)
888 tree decl = NULL_TREE;
890 if (type == NULL_TREE)
891 return NULL_TREE;
893 /* type is a declaration. */
894 if (DECL_P (type))
895 decl = type;
897 /* type is a typedef. */
898 if (TYPE_P (type) && TYPE_NAME (type) && DECL_P (TYPE_NAME (type)))
899 decl = TYPE_NAME (type);
901 /* TYPE_STUB_DECL has been set for type. */
902 if (TYPE_P (type) && TYPE_STUB_DECL (type) &&
903 DECL_P (TYPE_STUB_DECL (type)))
904 decl = TYPE_STUB_DECL (type);
906 return decl;
909 /* Return whether TYPE has static fields. */
911 static int
912 has_static_fields (const_tree type)
914 tree tmp;
916 for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
918 if (DECL_NAME (tmp) && TREE_STATIC (tmp))
919 return true;
921 return false;
924 /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
925 table). */
927 static int
928 is_tagged_type (const_tree type)
930 tree tmp;
932 if (!type || !RECORD_OR_UNION_TYPE_P (type))
933 return false;
935 for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
936 if (DECL_VINDEX (tmp))
937 return true;
939 return false;
942 /* Generate a legal Ada name from a C NAME, returning a malloc'd string.
943 SPACE_FOUND, if not NULL, is used to indicate whether a space was found in
944 NAME. */
946 static char *
947 to_ada_name (const char *name, int *space_found)
949 const char **names;
950 int len = strlen (name);
951 int j, len2 = 0;
952 int found = false;
953 char *s = XNEWVEC (char, len * 2 + 5);
954 char c;
956 if (space_found)
957 *space_found = false;
959 /* Add trailing "c_" if name is an Ada reserved word. */
960 for (names = ada_reserved; *names; names++)
961 if (!strcasecmp (name, *names))
963 s [len2++] = 'c';
964 s [len2++] = '_';
965 found = true;
966 break;
969 if (!found)
970 /* Add trailing "c_" if name is an potential case sensitive duplicate. */
971 for (names = c_duplicates; *names; names++)
972 if (!strcmp (name, *names))
974 s [len2++] = 'c';
975 s [len2++] = '_';
976 found = true;
977 break;
980 for (j = 0; name [j] == '_'; j++)
981 s [len2++] = 'u';
983 if (j > 0)
984 s [len2++] = '_';
985 else if (*name == '.' || *name == '$')
987 s [0] = 'a';
988 s [1] = 'n';
989 s [2] = 'o';
990 s [3] = 'n';
991 len2 = 4;
992 j++;
995 /* Replace unsuitable characters for Ada identifiers. */
997 for (; j < len; j++)
998 switch (name [j])
1000 case ' ':
1001 if (space_found)
1002 *space_found = true;
1003 s [len2++] = '_';
1004 break;
1006 /* ??? missing some C++ operators. */
1007 case '=':
1008 s [len2++] = '_';
1010 if (name [j + 1] == '=')
1012 j++;
1013 s [len2++] = 'e';
1014 s [len2++] = 'q';
1016 else
1018 s [len2++] = 'a';
1019 s [len2++] = 's';
1021 break;
1023 case '!':
1024 s [len2++] = '_';
1025 if (name [j + 1] == '=')
1027 j++;
1028 s [len2++] = 'n';
1029 s [len2++] = 'e';
1031 break;
1033 case '~':
1034 s [len2++] = '_';
1035 s [len2++] = 't';
1036 s [len2++] = 'i';
1037 break;
1039 case '&':
1040 case '|':
1041 case '^':
1042 s [len2++] = '_';
1043 s [len2++] = name [j] == '&' ? 'a' : name [j] == '|' ? 'o' : 'x';
1045 if (name [j + 1] == '=')
1047 j++;
1048 s [len2++] = 'e';
1050 break;
1052 case '+':
1053 case '-':
1054 case '*':
1055 case '/':
1056 case '(':
1057 case '[':
1058 if (s [len2 - 1] != '_')
1059 s [len2++] = '_';
1061 switch (name [j + 1]) {
1062 case '\0':
1063 j++;
1064 switch (name [j - 1]) {
1065 case '+': s [len2++] = 'p'; break; /* + */
1066 case '-': s [len2++] = 'm'; break; /* - */
1067 case '*': s [len2++] = 't'; break; /* * */
1068 case '/': s [len2++] = 'd'; break; /* / */
1070 break;
1072 case '=':
1073 j++;
1074 switch (name [j - 1]) {
1075 case '+': s [len2++] = 'p'; break; /* += */
1076 case '-': s [len2++] = 'm'; break; /* -= */
1077 case '*': s [len2++] = 't'; break; /* *= */
1078 case '/': s [len2++] = 'd'; break; /* /= */
1080 s [len2++] = 'a';
1081 break;
1083 case '-': /* -- */
1084 j++;
1085 s [len2++] = 'm';
1086 s [len2++] = 'm';
1087 break;
1089 case '+': /* ++ */
1090 j++;
1091 s [len2++] = 'p';
1092 s [len2++] = 'p';
1093 break;
1095 case ')': /* () */
1096 j++;
1097 s [len2++] = 'o';
1098 s [len2++] = 'p';
1099 break;
1101 case ']': /* [] */
1102 j++;
1103 s [len2++] = 'o';
1104 s [len2++] = 'b';
1105 break;
1108 break;
1110 case '<':
1111 case '>':
1112 c = name [j] == '<' ? 'l' : 'g';
1113 s [len2++] = '_';
1115 switch (name [j + 1]) {
1116 case '\0':
1117 s [len2++] = c;
1118 s [len2++] = 't';
1119 break;
1120 case '=':
1121 j++;
1122 s [len2++] = c;
1123 s [len2++] = 'e';
1124 break;
1125 case '>':
1126 j++;
1127 s [len2++] = 's';
1128 s [len2++] = 'r';
1129 break;
1130 case '<':
1131 j++;
1132 s [len2++] = 's';
1133 s [len2++] = 'l';
1134 break;
1135 default:
1136 break;
1138 break;
1140 case '_':
1141 if (len2 && s [len2 - 1] == '_')
1142 s [len2++] = 'u';
1143 /* fall through */
1145 default:
1146 s [len2++] = name [j];
1149 if (s [len2 - 1] == '_')
1150 s [len2++] = 'u';
1152 s [len2] = '\0';
1154 return s;
1157 /* Return true if DECL refers to a C++ class type for which a
1158 separate enclosing package has been or should be generated. */
1160 static bool
1161 separate_class_package (tree decl)
1163 if (decl)
1165 tree type = TREE_TYPE (decl);
1166 return type
1167 && TREE_CODE (type) == RECORD_TYPE
1168 && (TYPE_METHODS (type) || has_static_fields (type));
1170 else
1171 return false;
1174 static bool package_prefix = true;
1176 /* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
1177 syntax. LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1178 'with' clause rather than a regular 'with' clause. */
1180 static void
1181 pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
1182 int limited_access)
1184 const char *name = IDENTIFIER_POINTER (node);
1185 int space_found = false;
1186 char *s = to_ada_name (name, &space_found);
1187 tree decl;
1189 /* If the entity is a type and comes from another file, generate "package"
1190 prefix. */
1192 decl = get_underlying_decl (type);
1194 if (decl)
1196 expanded_location xloc = expand_location (decl_sloc (decl, false));
1198 if (xloc.file && xloc.line)
1200 if (xloc.file != source_file_base)
1202 switch (TREE_CODE (type))
1204 case ENUMERAL_TYPE:
1205 case INTEGER_TYPE:
1206 case REAL_TYPE:
1207 case FIXED_POINT_TYPE:
1208 case BOOLEAN_TYPE:
1209 case REFERENCE_TYPE:
1210 case POINTER_TYPE:
1211 case ARRAY_TYPE:
1212 case RECORD_TYPE:
1213 case UNION_TYPE:
1214 case QUAL_UNION_TYPE:
1215 case TYPE_DECL:
1217 char *s1 = get_ada_package (xloc.file);
1219 if (package_prefix)
1221 append_withs (s1, limited_access);
1222 pp_string (buffer, s1);
1223 pp_character (buffer, '.');
1225 free (s1);
1227 break;
1228 default:
1229 break;
1232 if (separate_class_package (decl))
1234 pp_string (buffer, "Class_");
1235 pp_string (buffer, s);
1236 pp_string (buffer, ".");
1243 if (space_found)
1244 if (!strcmp (s, "short_int"))
1245 pp_string (buffer, "short");
1246 else if (!strcmp (s, "short_unsigned_int"))
1247 pp_string (buffer, "unsigned_short");
1248 else if (!strcmp (s, "unsigned_int"))
1249 pp_string (buffer, "unsigned");
1250 else if (!strcmp (s, "long_int"))
1251 pp_string (buffer, "long");
1252 else if (!strcmp (s, "long_unsigned_int"))
1253 pp_string (buffer, "unsigned_long");
1254 else if (!strcmp (s, "long_long_int"))
1255 pp_string (buffer, "Long_Long_Integer");
1256 else if (!strcmp (s, "long_long_unsigned_int"))
1258 if (package_prefix)
1260 append_withs ("Interfaces.C.Extensions", false);
1261 pp_string (buffer, "Extensions.unsigned_long_long");
1263 else
1264 pp_string (buffer, "unsigned_long_long");
1266 else
1267 pp_string(buffer, s);
1268 else
1269 if (!strcmp (s, "bool"))
1271 if (package_prefix)
1273 append_withs ("Interfaces.C.Extensions", false);
1274 pp_string (buffer, "Extensions.bool");
1276 else
1277 pp_string (buffer, "bool");
1279 else
1280 pp_string(buffer, s);
1282 free (s);
1285 /* Dump in BUFFER the assembly name of T. */
1287 static void
1288 pp_asm_name (pretty_printer *buffer, tree t)
1290 tree name = DECL_ASSEMBLER_NAME (t);
1291 char *ada_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (name) + 1), *s;
1292 const char *ident = IDENTIFIER_POINTER (name);
1294 for (s = ada_name; *ident; ident++)
1296 if (*ident == ' ')
1297 break;
1298 else if (*ident != '*')
1299 *s++ = *ident;
1302 *s = '\0';
1303 pp_string (buffer, ada_name);
1306 /* Dump in BUFFER the name of a DECL node if set, following Ada syntax.
1307 LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1308 'with' clause rather than a regular 'with' clause. */
1310 static void
1311 dump_ada_decl_name (pretty_printer *buffer, tree decl, int limited_access)
1313 if (DECL_NAME (decl))
1314 pp_ada_tree_identifier (buffer, DECL_NAME (decl), decl, limited_access);
1315 else
1317 tree type_name = TYPE_NAME (TREE_TYPE (decl));
1319 if (!type_name)
1321 pp_string (buffer, "anon");
1322 if (TREE_CODE (decl) == FIELD_DECL)
1323 pp_scalar (buffer, "%d", DECL_UID (decl));
1324 else
1325 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (decl)));
1327 else if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1328 pp_ada_tree_identifier (buffer, type_name, decl, limited_access);
1332 /* Dump in BUFFER a name based on both T1 and T2, followed by S. */
1334 static void
1335 dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2, const char *s)
1337 if (DECL_NAME (t1))
1338 pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, false);
1339 else
1341 pp_string (buffer, "anon");
1342 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t1)));
1345 pp_character (buffer, '_');
1347 if (DECL_NAME (t1))
1348 pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, false);
1349 else
1351 pp_string (buffer, "anon");
1352 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t2)));
1355 pp_string (buffer, s);
1358 /* Dump in BUFFER pragma Import C/CPP on a given node T. */
1360 static void
1361 dump_ada_import (pretty_printer *buffer, tree t)
1363 const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
1364 int is_stdcall = TREE_CODE (t) == FUNCTION_DECL &&
1365 lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (t)));
1367 if (is_stdcall)
1368 pp_string (buffer, "pragma Import (Stdcall, ");
1369 else if (name [0] == '_' && name [1] == 'Z')
1370 pp_string (buffer, "pragma Import (CPP, ");
1371 else
1372 pp_string (buffer, "pragma Import (C, ");
1374 dump_ada_decl_name (buffer, t, false);
1375 pp_string (buffer, ", \"");
1377 if (is_stdcall)
1378 pp_string (buffer, IDENTIFIER_POINTER (DECL_NAME (t)));
1379 else
1380 pp_asm_name (buffer, t);
1382 pp_string (buffer, "\");");
1385 /* Check whether T and its type have different names, and append "the_"
1386 otherwise in BUFFER. */
1388 static void
1389 check_name (pretty_printer *buffer, tree t)
1391 const char *s;
1392 tree tmp = TREE_TYPE (t);
1394 while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp))
1395 tmp = TREE_TYPE (tmp);
1397 if (TREE_CODE (tmp) != FUNCTION_TYPE)
1399 if (TREE_CODE (tmp) == IDENTIFIER_NODE)
1400 s = IDENTIFIER_POINTER (tmp);
1401 else if (!TYPE_NAME (tmp))
1402 s = "";
1403 else if (TREE_CODE (TYPE_NAME (tmp)) == IDENTIFIER_NODE)
1404 s = IDENTIFIER_POINTER (TYPE_NAME (tmp));
1405 else
1406 s = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp)));
1408 if (!strcasecmp (IDENTIFIER_POINTER (DECL_NAME (t)), s))
1409 pp_string (buffer, "the_");
1413 /* Dump in BUFFER a function declaration FUNC with Ada syntax.
1414 IS_METHOD indicates whether FUNC is a C++ method.
1415 IS_CONSTRUCTOR whether FUNC is a C++ constructor.
1416 IS_DESTRUCTOR whether FUNC is a C++ destructor.
1417 SPC is the current indentation level. */
1419 static int
1420 dump_ada_function_declaration (pretty_printer *buffer, tree func,
1421 int is_method, int is_constructor,
1422 int is_destructor, int spc)
1424 tree arg;
1425 const tree node = TREE_TYPE (func);
1426 char buf [16];
1427 int num = 0, num_args = 0, have_args = true, have_ellipsis = false;
1429 /* Compute number of arguments. */
1430 arg = TYPE_ARG_TYPES (node);
1432 if (arg)
1434 while (TREE_CHAIN (arg) && arg != error_mark_node)
1436 num_args++;
1437 arg = TREE_CHAIN (arg);
1440 if (TREE_CODE (TREE_VALUE (arg)) != VOID_TYPE)
1442 num_args++;
1443 have_ellipsis = true;
1447 if (is_constructor)
1448 num_args--;
1450 if (is_destructor)
1451 num_args = 1;
1453 if (num_args > 2)
1454 newline_and_indent (buffer, spc + 1);
1456 if (num_args > 0)
1458 pp_space (buffer);
1459 pp_character (buffer, '(');
1462 if (TREE_CODE (func) == FUNCTION_DECL)
1463 arg = DECL_ARGUMENTS (func);
1464 else
1465 arg = NULL_TREE;
1467 if (arg == NULL_TREE)
1469 have_args = false;
1470 arg = TYPE_ARG_TYPES (node);
1472 if (arg && TREE_CODE (TREE_VALUE (arg)) == VOID_TYPE)
1473 arg = NULL_TREE;
1476 if (is_constructor)
1477 arg = TREE_CHAIN (arg);
1479 /* Print the argument names (if available) & types. */
1481 for (num = 1; num <= num_args; num++)
1483 if (have_args)
1485 if (DECL_NAME (arg))
1487 check_name (buffer, arg);
1488 pp_ada_tree_identifier (buffer, DECL_NAME (arg), 0, false);
1489 pp_string (buffer, " : ");
1491 else
1493 sprintf (buf, "arg%d : ", num);
1494 pp_string (buffer, buf);
1497 dump_generic_ada_node
1498 (buffer, TREE_TYPE (arg), node, NULL, spc, 0, true);
1500 else
1502 sprintf (buf, "arg%d : ", num);
1503 pp_string (buffer, buf);
1504 dump_generic_ada_node
1505 (buffer, TREE_VALUE (arg), node, NULL, spc, 0, true);
1508 if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg))
1509 && is_tagged_type (TREE_TYPE (TREE_TYPE (arg))))
1511 if (!is_method
1512 || (num != 1 || (!DECL_VINDEX (func) && !is_constructor)))
1513 pp_string (buffer, "'Class");
1516 arg = TREE_CHAIN (arg);
1518 if (num < num_args)
1520 pp_character (buffer, ';');
1522 if (num_args > 2)
1523 newline_and_indent (buffer, spc + INDENT_INCR);
1524 else
1525 pp_space (buffer);
1529 if (have_ellipsis)
1531 pp_string (buffer, " -- , ...");
1532 newline_and_indent (buffer, spc + INDENT_INCR);
1535 if (num_args > 0)
1536 pp_character (buffer, ')');
1537 return num_args;
1540 /* Dump in BUFFER all the domains associated with an array NODE,
1541 using Ada syntax. SPC is the current indentation level. */
1543 static void
1544 dump_ada_array_domains (pretty_printer *buffer, tree node, int spc)
1546 int first = 1;
1547 pp_character (buffer, '(');
1549 for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node))
1551 tree domain = TYPE_DOMAIN (node);
1553 if (domain)
1555 tree min = TYPE_MIN_VALUE (domain);
1556 tree max = TYPE_MAX_VALUE (domain);
1558 if (!first)
1559 pp_string (buffer, ", ");
1560 first = 0;
1562 if (min)
1563 dump_generic_ada_node (buffer, min, NULL_TREE, NULL, spc, 0, true);
1564 pp_string (buffer, " .. ");
1566 /* If the upper bound is zero, gcc may generate a NULL_TREE
1567 for TYPE_MAX_VALUE rather than an integer_cst. */
1568 if (max)
1569 dump_generic_ada_node (buffer, max, NULL_TREE, NULL, spc, 0, true);
1570 else
1571 pp_string (buffer, "0");
1573 else
1574 pp_string (buffer, "size_t");
1576 pp_character (buffer, ')');
1579 /* Dump in BUFFER file:line information related to NODE. */
1581 static void
1582 dump_sloc (pretty_printer *buffer, tree node)
1584 expanded_location xloc;
1586 xloc.file = NULL;
1588 if (TREE_CODE_CLASS (TREE_CODE (node)) == tcc_declaration)
1589 xloc = expand_location (DECL_SOURCE_LOCATION (node));
1590 else if (EXPR_HAS_LOCATION (node))
1591 xloc = expand_location (EXPR_LOCATION (node));
1593 if (xloc.file)
1595 pp_string (buffer, xloc.file);
1596 pp_string (buffer, ":");
1597 pp_decimal_int (buffer, xloc.line);
1601 /* Return true if T designates a one dimension array of "char". */
1603 static bool
1604 is_char_array (tree t)
1606 tree tmp;
1607 int num_dim = 0;
1609 /* Retrieve array's type. */
1610 tmp = t;
1611 while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1613 num_dim++;
1614 tmp = TREE_TYPE (tmp);
1617 tmp = TREE_TYPE (tmp);
1618 return num_dim == 1 && TREE_CODE (tmp) == INTEGER_TYPE
1619 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp))), "char");
1622 /* Dump in BUFFER an array type T in Ada syntax. Assume that the "type"
1623 keyword and name have already been printed. SPC is the indentation
1624 level. */
1626 static void
1627 dump_ada_array_type (pretty_printer *buffer, tree t, int spc)
1629 tree tmp;
1630 bool char_array = is_char_array (t);
1632 /* Special case char arrays. */
1633 if (char_array)
1635 pp_string (buffer, "Interfaces.C.char_array ");
1637 else
1638 pp_string (buffer, "array ");
1640 /* Print the dimensions. */
1641 dump_ada_array_domains (buffer, TREE_TYPE (t), spc);
1643 /* Retrieve array's type. */
1644 tmp = TREE_TYPE (t);
1645 while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1646 tmp = TREE_TYPE (tmp);
1648 /* Print array's type. */
1649 if (!char_array)
1651 pp_string (buffer, " of ");
1653 if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE)
1654 pp_string (buffer, "aliased ");
1656 dump_generic_ada_node
1657 (buffer, TREE_TYPE (tmp), TREE_TYPE (t), NULL, spc, false, true);
1661 /* Dump in BUFFER type names associated with a template, each prepended with
1662 '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.
1663 CPP_CHECK is used to perform C++ queries on nodes.
1664 SPC is the indentation level. */
1666 static void
1667 dump_template_types (pretty_printer *buffer, tree types,
1668 int (*cpp_check)(tree, cpp_operation), int spc)
1670 size_t i;
1671 size_t len = TREE_VEC_LENGTH (types);
1673 for (i = 0; i < len; i++)
1675 tree elem = TREE_VEC_ELT (types, i);
1676 pp_character (buffer, '_');
1677 if (!dump_generic_ada_node (buffer, elem, 0, cpp_check, spc, false, true))
1679 pp_string (buffer, "unknown");
1680 pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
1685 /* Dump in BUFFER the contents of all class instantiations associated with
1686 a given template T. CPP_CHECK is used to perform C++ queries on nodes.
1687 SPC is the indentation level. */
1689 static int
1690 dump_ada_template (pretty_printer *buffer, tree t,
1691 int (*cpp_check)(tree, cpp_operation), int spc)
1693 tree inst = DECL_VINDEX (t);
1694 /* DECL_VINDEX is DECL_TEMPLATE_INSTANTIATIONS in this context. */
1695 int num_inst = 0;
1697 while (inst && inst != error_mark_node)
1699 tree types = TREE_PURPOSE (inst);
1700 tree instance = TREE_VALUE (inst);
1702 if (TREE_VEC_LENGTH (types) == 0)
1703 break;
1705 if (!TYPE_P (instance) || !TYPE_METHODS (instance))
1706 break;
1708 num_inst++;
1709 INDENT (spc);
1710 pp_string (buffer, "package ");
1711 package_prefix = false;
1712 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1713 dump_template_types (buffer, types, cpp_check, spc);
1714 pp_string (buffer, " is");
1715 spc += INDENT_INCR;
1716 newline_and_indent (buffer, spc);
1718 TREE_VISITED (get_underlying_decl (instance)) = 1;
1719 pp_string (buffer, "type ");
1720 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1721 package_prefix = true;
1723 if (is_tagged_type (instance))
1724 pp_string (buffer, " is tagged limited ");
1725 else
1726 pp_string (buffer, " is limited ");
1728 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, false);
1729 pp_newline (buffer);
1730 spc -= INDENT_INCR;
1731 newline_and_indent (buffer, spc);
1733 pp_string (buffer, "end;");
1734 newline_and_indent (buffer, spc);
1735 pp_string (buffer, "use ");
1736 package_prefix = false;
1737 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1738 dump_template_types (buffer, types, cpp_check, spc);
1739 package_prefix = true;
1740 pp_semicolon (buffer);
1741 pp_newline (buffer);
1742 pp_newline (buffer);
1744 inst = TREE_CHAIN (inst);
1747 return num_inst > 0;
1750 /* Return true if NODE is a simple enum types, that can be mapped to an
1751 Ada enum type directly. */
1753 static bool
1754 is_simple_enum (tree node)
1756 unsigned HOST_WIDE_INT count = 0;
1757 tree value;
1759 for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
1761 tree int_val = TREE_VALUE (value);
1763 if (TREE_CODE (int_val) != INTEGER_CST)
1764 int_val = DECL_INITIAL (int_val);
1766 if (!host_integerp (int_val, 0))
1767 return false;
1768 else if (TREE_INT_CST_LOW (int_val) != count)
1769 return false;
1771 count++;
1774 return true;
1777 static bool in_function = true;
1778 static bool bitfield_used = false;
1780 /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
1781 TYPE. CPP_CHECK is used to perform C++ queries on nodes. SPC is the
1782 indentation level. LIMITED_ACCESS indicates whether NODE can be referenced
1783 via a "limited with" clause. NAME_ONLY indicates whether we should only
1784 dump the name of NODE, instead of its full declaration. */
1786 static int
1787 dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
1788 int (*cpp_check)(tree, cpp_operation), int spc,
1789 int limited_access, bool name_only)
1791 if (node == NULL_TREE)
1792 return 0;
1794 switch (TREE_CODE (node))
1796 case ERROR_MARK:
1797 pp_string (buffer, "<<< error >>>");
1798 return 0;
1800 case IDENTIFIER_NODE:
1801 pp_ada_tree_identifier (buffer, node, type, limited_access);
1802 break;
1804 case TREE_LIST:
1805 pp_string (buffer, "--- unexpected node: TREE_LIST");
1806 return 0;
1808 case TREE_BINFO:
1809 dump_generic_ada_node
1810 (buffer, BINFO_TYPE (node), type, cpp_check,
1811 spc, limited_access, name_only);
1813 case TREE_VEC:
1814 pp_string (buffer, "--- unexpected node: TREE_VEC");
1815 return 0;
1817 case VOID_TYPE:
1818 if (package_prefix)
1820 append_withs ("System", false);
1821 pp_string (buffer, "System.Address");
1823 else
1824 pp_string (buffer, "address");
1825 break;
1827 case VECTOR_TYPE:
1828 pp_string (buffer, "<vector>");
1829 break;
1831 case COMPLEX_TYPE:
1832 pp_string (buffer, "<complex>");
1833 break;
1835 case ENUMERAL_TYPE:
1836 if (name_only)
1837 dump_generic_ada_node
1838 (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true);
1839 else
1841 tree value = TYPE_VALUES (node);
1843 if (is_simple_enum (node))
1845 bool first = true;
1846 spc += INDENT_INCR;
1847 newline_and_indent (buffer, spc - 1);
1848 pp_string (buffer, "(");
1849 for (; value; value = TREE_CHAIN (value))
1851 if (first)
1852 first = false;
1853 else
1855 pp_string (buffer, ",");
1856 newline_and_indent (buffer, spc);
1859 pp_ada_tree_identifier
1860 (buffer, TREE_PURPOSE (value), node, false);
1862 pp_string (buffer, ");");
1863 spc -= INDENT_INCR;
1864 newline_and_indent (buffer, spc);
1865 pp_string (buffer, "pragma Convention (C, ");
1866 dump_generic_ada_node
1867 (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
1868 cpp_check, spc, 0, true);
1869 pp_string (buffer, ")");
1871 else
1873 pp_string (buffer, "unsigned");
1874 for (; value; value = TREE_CHAIN (value))
1876 pp_semicolon (buffer);
1877 newline_and_indent (buffer, spc);
1879 pp_ada_tree_identifier
1880 (buffer, TREE_PURPOSE (value), node, false);
1881 pp_string (buffer, " : constant ");
1883 dump_generic_ada_node
1884 (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
1885 cpp_check, spc, 0, true);
1887 pp_string (buffer, " := ");
1888 dump_generic_ada_node
1889 (buffer,
1890 TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
1891 TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
1892 node, cpp_check, spc, false, true);
1896 break;
1898 case INTEGER_TYPE:
1899 case REAL_TYPE:
1900 case FIXED_POINT_TYPE:
1901 case BOOLEAN_TYPE:
1903 enum tree_code_class tclass;
1905 tclass = TREE_CODE_CLASS (TREE_CODE (node));
1907 if (tclass == tcc_declaration)
1909 if (DECL_NAME (node))
1910 pp_ada_tree_identifier
1911 (buffer, DECL_NAME (node), 0, limited_access);
1912 else
1913 pp_string (buffer, "<unnamed type decl>");
1915 else if (tclass == tcc_type)
1917 if (TYPE_NAME (node))
1919 if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
1920 pp_ada_tree_identifier (buffer, TYPE_NAME (node),
1921 node, limited_access);
1922 else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
1923 && DECL_NAME (TYPE_NAME (node)))
1924 dump_ada_decl_name (buffer, TYPE_NAME (node), limited_access);
1925 else
1926 pp_string (buffer, "<unnamed type>");
1928 else if (TREE_CODE (node) == INTEGER_TYPE)
1930 append_withs ("Interfaces.C.Extensions", false);
1931 bitfield_used = true;
1933 if (TYPE_PRECISION (node) == 1)
1934 pp_string (buffer, "Extensions.Unsigned_1");
1935 else
1937 pp_string (buffer, (TYPE_UNSIGNED (node)
1938 ? "Extensions.Unsigned_"
1939 : "Extensions.Signed_"));
1940 pp_decimal_int (buffer, TYPE_PRECISION (node));
1943 else
1944 pp_string (buffer, "<unnamed type>");
1946 break;
1949 case POINTER_TYPE:
1950 case REFERENCE_TYPE:
1951 if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
1953 tree fnode = TREE_TYPE (node);
1954 bool is_function;
1955 bool prev_in_function = in_function;
1957 if (VOID_TYPE_P (TREE_TYPE (fnode)))
1959 is_function = false;
1960 pp_string (buffer, "access procedure");
1962 else
1964 is_function = true;
1965 pp_string (buffer, "access function");
1968 in_function = is_function;
1969 dump_ada_function_declaration
1970 (buffer, node, false, false, false, spc + INDENT_INCR);
1971 in_function = prev_in_function;
1973 if (is_function)
1975 pp_string (buffer, " return ");
1976 dump_generic_ada_node
1977 (buffer, TREE_TYPE (fnode), type, cpp_check, spc, 0, true);
1980 else
1982 int is_access = false;
1983 unsigned int quals = TYPE_QUALS (TREE_TYPE (node));
1985 if (name_only && TYPE_NAME (node))
1986 dump_generic_ada_node
1987 (buffer, TYPE_NAME (node), node, cpp_check,
1988 spc, limited_access, true);
1989 else if (VOID_TYPE_P (TREE_TYPE (node)))
1991 if (!name_only)
1992 pp_string (buffer, "new ");
1993 if (package_prefix)
1995 append_withs ("System", false);
1996 pp_string (buffer, "System.Address");
1998 else
1999 pp_string (buffer, "address");
2001 else
2003 if (TREE_CODE (node) == POINTER_TYPE
2004 && TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE
2005 && !strcmp
2006 (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME
2007 (TREE_TYPE (node)))), "char"))
2009 if (!name_only)
2010 pp_string (buffer, "new ");
2012 if (package_prefix)
2014 pp_string (buffer, "Interfaces.C.Strings.chars_ptr");
2015 append_withs ("Interfaces.C.Strings", false);
2017 else
2018 pp_string (buffer, "chars_ptr");
2020 else
2022 /* For now, handle all access-to-access or
2023 access-to-unknown-structs as opaque system.address. */
2025 tree type_name = TYPE_NAME (TREE_TYPE (node));
2026 const_tree typ2 = !type ||
2027 DECL_P (type) ? type : TYPE_NAME (type);
2028 const_tree underlying_type =
2029 get_underlying_decl (TREE_TYPE (node));
2031 if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE
2032 /* Pointer to pointer. */
2034 || (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2035 && (!underlying_type
2036 || !TYPE_FIELDS (TREE_TYPE (underlying_type))))
2037 /* Pointer to opaque structure. */
2039 || underlying_type == NULL_TREE
2040 || (!typ2
2041 && !TREE_VISITED (underlying_type)
2042 && !TREE_VISITED (type_name)
2043 && !is_tagged_type (TREE_TYPE (node))
2044 && DECL_SOURCE_FILE (underlying_type)
2045 == source_file_base)
2046 || (type_name && typ2
2047 && DECL_P (underlying_type)
2048 && DECL_P (typ2)
2049 && decl_sloc (underlying_type, true)
2050 > decl_sloc (typ2, true)
2051 && DECL_SOURCE_FILE (underlying_type)
2052 == DECL_SOURCE_FILE (typ2)))
2054 if (package_prefix)
2056 append_withs ("System", false);
2057 if (!name_only)
2058 pp_string (buffer, "new ");
2059 pp_string (buffer, "System.Address");
2061 else
2062 pp_string (buffer, "address");
2063 return spc;
2066 if (!package_prefix)
2067 pp_string (buffer, "access");
2068 else if (AGGREGATE_TYPE_P (TREE_TYPE (node)))
2070 if (!type || TREE_CODE (type) != FUNCTION_DECL)
2072 pp_string (buffer, "access ");
2073 is_access = true;
2075 if (quals & TYPE_QUAL_CONST)
2076 pp_string (buffer, "constant ");
2077 else if (!name_only)
2078 pp_string (buffer, "all ");
2080 else if (quals & TYPE_QUAL_CONST)
2081 pp_string (buffer, "in ");
2082 else if (in_function)
2084 is_access = true;
2085 pp_string (buffer, "access ");
2087 else
2089 is_access = true;
2090 pp_string (buffer, "access ");
2091 /* ??? should be configurable: access or in out. */
2094 else
2096 is_access = true;
2097 pp_string (buffer, "access ");
2099 if (!name_only)
2100 pp_string (buffer, "all ");
2103 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2104 && type_name != NULL_TREE)
2105 dump_generic_ada_node
2106 (buffer, type_name,
2107 TREE_TYPE (node), cpp_check, spc, is_access, true);
2108 else
2109 dump_generic_ada_node
2110 (buffer, TREE_TYPE (node), TREE_TYPE (node),
2111 cpp_check, spc, 0, true);
2115 break;
2117 case ARRAY_TYPE:
2118 if (name_only)
2119 dump_generic_ada_node
2120 (buffer, TYPE_NAME (node), node, cpp_check,
2121 spc, limited_access, true);
2122 else
2123 dump_ada_array_type (buffer, node, spc);
2124 break;
2126 case RECORD_TYPE:
2127 case UNION_TYPE:
2128 case QUAL_UNION_TYPE:
2129 if (name_only)
2131 if (TYPE_NAME (node))
2132 dump_generic_ada_node
2133 (buffer, TYPE_NAME (node), node, cpp_check,
2134 spc, limited_access, true);
2135 else
2137 pp_string (buffer, "anon_");
2138 pp_scalar (buffer, "%d", TYPE_UID (node));
2141 else
2142 print_ada_struct_decl
2143 (buffer, node, type, cpp_check, spc, true);
2144 break;
2146 case INTEGER_CST:
2147 if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE)
2149 pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
2150 pp_string (buffer, "B"); /* pseudo-unit */
2152 else if (!host_integerp (node, 0))
2154 tree val = node;
2155 unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (val);
2156 HOST_WIDE_INT high = TREE_INT_CST_HIGH (val);
2158 if (tree_int_cst_sgn (val) < 0)
2160 pp_character (buffer, '-');
2161 high = ~high + !low;
2162 low = -low;
2164 sprintf (pp_buffer (buffer)->digit_buffer,
2165 HOST_WIDE_INT_PRINT_DOUBLE_HEX,
2166 (unsigned HOST_WIDE_INT) high, low);
2167 pp_string (buffer, pp_buffer (buffer)->digit_buffer);
2169 else
2170 pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
2171 break;
2173 case REAL_CST:
2174 case FIXED_CST:
2175 case COMPLEX_CST:
2176 case STRING_CST:
2177 case VECTOR_CST:
2178 return 0;
2180 case FUNCTION_DECL:
2181 case CONST_DECL:
2182 dump_ada_decl_name (buffer, node, limited_access);
2183 break;
2185 case TYPE_DECL:
2186 if (DECL_IS_BUILTIN (node))
2188 /* Don't print the declaration of built-in types. */
2190 if (name_only)
2192 /* If we're in the middle of a declaration, defaults to
2193 System.Address. */
2194 if (package_prefix)
2196 append_withs ("System", false);
2197 pp_string (buffer, "System.Address");
2199 else
2200 pp_string (buffer, "address");
2202 break;
2205 if (name_only)
2206 dump_ada_decl_name (buffer, node, limited_access);
2207 else
2209 if (is_tagged_type (TREE_TYPE (node)))
2211 tree tmp = TYPE_FIELDS (TREE_TYPE (node));
2212 int first = 1;
2214 /* Look for ancestors. */
2215 for (; tmp; tmp = TREE_CHAIN (tmp))
2217 if (!DECL_NAME (tmp) && is_tagged_type (TREE_TYPE (tmp)))
2219 if (first)
2221 pp_string (buffer, "limited new ");
2222 first = 0;
2224 else
2225 pp_string (buffer, " and ");
2227 dump_ada_decl_name
2228 (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
2232 pp_string (buffer, first ? "tagged limited " : " with ");
2234 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2235 && TYPE_METHODS (TREE_TYPE (node)))
2236 pp_string (buffer, "limited ");
2238 dump_generic_ada_node
2239 (buffer, TREE_TYPE (node), type, cpp_check, spc, false, false);
2241 break;
2243 case VAR_DECL:
2244 case PARM_DECL:
2245 case FIELD_DECL:
2246 case NAMESPACE_DECL:
2247 dump_ada_decl_name (buffer, node, false);
2248 break;
2250 default:
2251 /* Ignore other nodes (e.g. expressions). */
2252 return 0;
2255 return 1;
2258 /* Dump in BUFFER NODE's methods. CPP_CHECK is used to perform C++ queries on
2259 nodes. SPC is the indentation level. */
2261 static void
2262 print_ada_methods (pretty_printer *buffer, tree node,
2263 int (*cpp_check)(tree, cpp_operation), int spc)
2265 tree tmp = TYPE_METHODS (node);
2266 int res = 1;
2268 if (tmp)
2270 pp_semicolon (buffer);
2272 for (; tmp; tmp = TREE_CHAIN (tmp))
2274 if (res)
2276 pp_newline (buffer);
2277 pp_newline (buffer);
2279 res = print_ada_declaration (buffer, tmp, node, cpp_check, spc);
2284 /* Dump in BUFFER anonymous types nested inside T's definition.
2285 PARENT is the parent node of T.
2286 FORWARD indicates whether a forward declaration of T should be generated.
2287 CPP_CHECK is used to perform C++ queries on
2288 nodes. SPC is the indentation level. */
2290 static void
2291 dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
2292 int (*cpp_check)(tree, cpp_operation), int spc)
2294 tree field, outer, decl;
2296 /* Avoid recursing over the same tree. */
2297 if (TREE_VISITED (t))
2298 return;
2300 /* Find possible anonymous arrays/unions/structs recursively. */
2302 outer = TREE_TYPE (t);
2304 if (outer == NULL_TREE)
2305 return;
2307 if (forward)
2309 pp_string (buffer, "type ");
2310 dump_generic_ada_node
2311 (buffer, t, t, cpp_check, spc, false, true);
2312 pp_semicolon (buffer);
2313 newline_and_indent (buffer, spc);
2314 TREE_VISITED (t) = 1;
2317 field = TYPE_FIELDS (outer);
2318 while (field)
2320 if ((TREE_TYPE (field) != outer
2321 || (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2322 && TREE_TYPE (TREE_TYPE (field)) != outer))
2323 && (!TYPE_NAME (TREE_TYPE (field))
2324 || (TREE_CODE (field) == TYPE_DECL
2325 && DECL_NAME (field) != DECL_NAME (t)
2326 && TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (outer))))
2328 switch (TREE_CODE (TREE_TYPE (field)))
2330 case POINTER_TYPE:
2331 decl = TREE_TYPE (TREE_TYPE (field));
2333 if (TREE_CODE (decl) == FUNCTION_TYPE)
2334 for (decl = TREE_TYPE (decl);
2335 decl && TREE_CODE (decl) == POINTER_TYPE;
2336 decl = TREE_TYPE (decl));
2338 decl = get_underlying_decl (decl);
2340 if (decl
2341 && DECL_P (decl)
2342 && decl_sloc (decl, true) > decl_sloc (t, true)
2343 && DECL_SOURCE_FILE (decl) == DECL_SOURCE_FILE (t)
2344 && !TREE_VISITED (decl)
2345 && !DECL_IS_BUILTIN (decl)
2346 && (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
2347 || TYPE_FIELDS (TREE_TYPE (decl))))
2349 /* Generate forward declaration. */
2351 pp_string (buffer, "type ");
2352 dump_generic_ada_node
2353 (buffer, decl, 0, cpp_check, spc, false, true);
2354 pp_semicolon (buffer);
2355 newline_and_indent (buffer, spc);
2357 /* Ensure we do not generate duplicate forward
2358 declarations for this type. */
2359 TREE_VISITED (decl) = 1;
2361 break;
2363 case ARRAY_TYPE:
2364 /* Special case char arrays. */
2365 if (is_char_array (field))
2366 pp_string (buffer, "sub");
2368 pp_string (buffer, "type ");
2369 dump_ada_double_name (buffer, parent, field, "_array is ");
2370 dump_ada_array_type (buffer, field, spc);
2371 pp_semicolon (buffer);
2372 newline_and_indent (buffer, spc);
2373 break;
2375 case UNION_TYPE:
2376 TREE_VISITED (t) = 1;
2377 dump_nested_types (buffer, field, t, false, cpp_check, spc);
2379 pp_string (buffer, "type ");
2381 if (TYPE_NAME (TREE_TYPE (field)))
2383 dump_generic_ada_node
2384 (buffer, TYPE_NAME (TREE_TYPE (field)), 0, cpp_check,
2385 spc, false, true);
2386 pp_string (buffer, " (discr : unsigned := 0) is ");
2387 print_ada_struct_decl
2388 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2390 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2391 dump_generic_ada_node
2392 (buffer, TREE_TYPE (field), 0, cpp_check,
2393 spc, false, true);
2394 pp_string (buffer, ");");
2395 newline_and_indent (buffer, spc);
2397 pp_string (buffer, "pragma Unchecked_Union (");
2398 dump_generic_ada_node
2399 (buffer, TREE_TYPE (field), 0, cpp_check,
2400 spc, false, true);
2401 pp_string (buffer, ");");
2403 else
2405 dump_ada_double_name
2406 (buffer, parent, field,
2407 "_union (discr : unsigned := 0) is ");
2408 print_ada_struct_decl
2409 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2410 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2411 dump_ada_double_name (buffer, parent, field, "_union);");
2412 newline_and_indent (buffer, spc);
2414 pp_string (buffer, "pragma Unchecked_Union (");
2415 dump_ada_double_name (buffer, parent, field, "_union);");
2418 newline_and_indent (buffer, spc);
2419 break;
2421 case RECORD_TYPE:
2422 if (TYPE_NAME (TREE_TYPE (t)) && !TREE_VISITED (t))
2424 pp_string (buffer, "type ");
2425 dump_generic_ada_node
2426 (buffer, t, parent, 0, spc, false, true);
2427 pp_semicolon (buffer);
2428 newline_and_indent (buffer, spc);
2431 TREE_VISITED (t) = 1;
2432 dump_nested_types (buffer, field, t, false, cpp_check, spc);
2433 pp_string (buffer, "type ");
2435 if (TYPE_NAME (TREE_TYPE (field)))
2437 dump_generic_ada_node
2438 (buffer, TREE_TYPE (field), 0, cpp_check,
2439 spc, false, true);
2440 pp_string (buffer, " is ");
2441 print_ada_struct_decl
2442 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2443 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2444 dump_generic_ada_node
2445 (buffer, TREE_TYPE (field), 0, cpp_check,
2446 spc, false, true);
2447 pp_string (buffer, ");");
2449 else
2451 dump_ada_double_name
2452 (buffer, parent, field, "_struct is ");
2453 print_ada_struct_decl
2454 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2455 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2456 dump_ada_double_name (buffer, parent, field, "_struct);");
2459 newline_and_indent (buffer, spc);
2460 break;
2462 default:
2463 break;
2466 field = TREE_CHAIN (field);
2469 TREE_VISITED (t) = 1;
2472 /* Dump in BUFFER destructor spec corresponding to T. */
2474 static void
2475 print_destructor (pretty_printer *buffer, tree t)
2477 const char *s = IDENTIFIER_POINTER (DECL_NAME (t));
2479 if (*s == '_')
2480 for (s += 2; *s != ' '; s++)
2481 pp_character (buffer, *s);
2482 else
2484 pp_string (buffer, "Delete_");
2485 pp_ada_tree_identifier (buffer, DECL_NAME (t), t, false);
2489 /* Return the name of type T. */
2491 static const char *
2492 type_name (tree t)
2494 tree n = TYPE_NAME (t);
2496 if (TREE_CODE (n) == IDENTIFIER_NODE)
2497 return IDENTIFIER_POINTER (n);
2498 else
2499 return IDENTIFIER_POINTER (DECL_NAME (n));
2502 /* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
2503 CPP_CHECK is used to perform C++ queries on nodes. SPC is the indentation
2504 level. Return 1 if a declaration was printed, 0 otherwise. */
2506 static int
2507 print_ada_declaration (pretty_printer *buffer, tree t, tree type,
2508 int (*cpp_check)(tree, cpp_operation), int spc)
2510 int is_var = 0, need_indent = 0;
2511 int is_class = false;
2512 tree name = TYPE_NAME (TREE_TYPE (t));
2513 tree decl_name = DECL_NAME (t);
2514 bool dump_internal = get_dump_file_info (TDI_ada)->flags & TDF_RAW;
2515 tree orig = NULL_TREE;
2517 if (cpp_check && cpp_check (t, IS_TEMPLATE))
2518 return dump_ada_template (buffer, t, cpp_check, spc);
2520 if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
2521 /* Skip enumeral values: will be handled as part of the type itself. */
2522 return 0;
2524 if (TREE_CODE (t) == TYPE_DECL)
2526 orig = DECL_ORIGINAL_TYPE (t);
2528 if (orig && TYPE_STUB_DECL (orig))
2530 tree stub = TYPE_STUB_DECL (orig);
2531 tree typ = TREE_TYPE (stub);
2533 if (TYPE_NAME (typ))
2535 /* If types have same representation, and same name (ignoring
2536 casing), then ignore the second type. */
2537 if (type_name (typ) == type_name (TREE_TYPE (t))
2538 || !strcasecmp (type_name (typ), type_name (TREE_TYPE (t))))
2539 return 0;
2541 INDENT (spc);
2543 if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
2545 pp_string (buffer, "-- skipped empty struct ");
2546 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2548 else
2550 if (!TREE_VISITED (stub)
2551 && DECL_SOURCE_FILE (stub) == source_file_base)
2552 dump_nested_types
2553 (buffer, stub, stub, true, cpp_check, spc);
2555 pp_string (buffer, "subtype ");
2556 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2557 pp_string (buffer, " is ");
2558 dump_generic_ada_node
2559 (buffer, typ, type, 0, spc, false, true);
2560 pp_semicolon (buffer);
2562 return 1;
2566 /* Skip unnamed or anonymous structs/unions/enum types. */
2567 if (!orig && !decl_name && !name)
2569 tree tmp;
2570 location_t sloc;
2572 if (cpp_check || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
2573 return 0;
2575 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
2577 /* Search next items until finding a named type decl. */
2578 sloc = decl_sloc_common (t, true, true);
2580 for (tmp = TREE_CHAIN (t); tmp; tmp = TREE_CHAIN (tmp))
2582 if (TREE_CODE (tmp) == TYPE_DECL
2583 && (DECL_NAME (tmp) || TYPE_NAME (TREE_TYPE (tmp))))
2585 /* If same sloc, it means we can ignore the anonymous
2586 struct. */
2587 if (decl_sloc_common (tmp, true, true) == sloc)
2588 return 0;
2589 else
2590 break;
2593 if (tmp == NULL)
2594 return 0;
2598 if (!orig
2599 && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE
2600 && decl_name
2601 && (*IDENTIFIER_POINTER (decl_name) == '.'
2602 || *IDENTIFIER_POINTER (decl_name) == '$'))
2603 /* Skip anonymous enum types (duplicates of real types). */
2604 return 0;
2606 INDENT (spc);
2608 switch (TREE_CODE (TREE_TYPE (t)))
2610 case RECORD_TYPE:
2611 case UNION_TYPE:
2612 case QUAL_UNION_TYPE:
2613 /* Skip empty structs (typically forward references to real
2614 structs). */
2615 if (!TYPE_FIELDS (TREE_TYPE (t)))
2617 pp_string (buffer, "-- skipped empty struct ");
2618 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2619 return 1;
2622 if (decl_name
2623 && (*IDENTIFIER_POINTER (decl_name) == '.'
2624 || *IDENTIFIER_POINTER (decl_name) == '$'))
2626 pp_string (buffer, "-- skipped anonymous struct ");
2627 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2628 TREE_VISITED (t) = 1;
2629 return 1;
2632 if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2633 pp_string (buffer, "subtype ");
2634 else
2636 dump_nested_types (buffer, t, t, false, cpp_check, spc);
2638 if (separate_class_package (t))
2640 is_class = true;
2641 pp_string (buffer, "package Class_");
2642 dump_generic_ada_node
2643 (buffer, t, type, 0, spc, false, true);
2644 pp_string (buffer, " is");
2645 spc += INDENT_INCR;
2646 newline_and_indent (buffer, spc);
2649 pp_string (buffer, "type ");
2651 break;
2653 case ARRAY_TYPE:
2654 case POINTER_TYPE:
2655 case REFERENCE_TYPE:
2656 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2657 || is_char_array (t))
2658 pp_string (buffer, "subtype ");
2659 else
2660 pp_string (buffer, "type ");
2661 break;
2663 case FUNCTION_TYPE:
2664 pp_string (buffer, "-- skipped function type ");
2665 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2666 return 1;
2667 break;
2669 case ENUMERAL_TYPE:
2670 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2671 || !is_simple_enum (TREE_TYPE (t)))
2672 pp_string (buffer, "subtype ");
2673 else
2674 pp_string (buffer, "type ");
2675 break;
2677 default:
2678 pp_string (buffer, "subtype ");
2680 TREE_VISITED (t) = 1;
2682 else
2684 if (!dump_internal
2685 && TREE_CODE (t) == VAR_DECL
2686 && decl_name
2687 && *IDENTIFIER_POINTER (decl_name) == '_')
2688 return 0;
2690 need_indent = 1;
2693 /* Print the type and name. */
2694 if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
2696 if (need_indent)
2697 INDENT (spc);
2699 /* Print variable's name. */
2700 dump_generic_ada_node (buffer, t, type, cpp_check, spc, false, true);
2702 if (TREE_CODE (t) == TYPE_DECL)
2704 pp_string (buffer, " is ");
2706 if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2707 dump_generic_ada_node
2708 (buffer, TYPE_NAME (orig), type,
2709 cpp_check, spc, false, true);
2710 else
2711 dump_ada_array_type (buffer, t, spc);
2713 else
2715 tree tmp = TYPE_NAME (TREE_TYPE (t));
2717 if (spc == INDENT_INCR || TREE_STATIC (t))
2718 is_var = 1;
2720 pp_string (buffer, " : ");
2722 if (tmp)
2724 if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE
2725 && TREE_CODE (tmp) != INTEGER_TYPE)
2726 pp_string (buffer, "aliased ");
2728 dump_generic_ada_node (buffer, tmp, type, 0, spc, false, true);
2730 else
2732 pp_string (buffer, "aliased ");
2734 if (!type)
2735 dump_ada_array_type (buffer, t, spc);
2736 else
2737 dump_ada_double_name (buffer, type, t, "_array");
2741 else if (TREE_CODE (t) == FUNCTION_DECL)
2743 bool is_function = true, is_method, is_abstract_class = false;
2744 tree decl_name = DECL_NAME (t);
2745 int prev_in_function = in_function;
2746 bool is_abstract = false;
2747 bool is_constructor = false;
2748 bool is_destructor = false;
2749 bool is_copy_constructor = false;
2751 if (!decl_name)
2752 return 0;
2754 if (cpp_check)
2756 is_abstract = cpp_check (t, IS_ABSTRACT);
2757 is_constructor = cpp_check (t, IS_CONSTRUCTOR);
2758 is_destructor = cpp_check (t, IS_DESTRUCTOR);
2759 is_copy_constructor = cpp_check (t, IS_COPY_CONSTRUCTOR);
2762 /* Skip __comp_dtor destructor which is redundant with the '~class()'
2763 destructor. */
2764 if (is_destructor
2765 && !strncmp (IDENTIFIER_POINTER (decl_name), "__comp", 6))
2766 return 0;
2768 /* Skip copy constructors: some are internal only, and those that are
2769 not cannot be called easily from Ada anyway. */
2770 if (is_copy_constructor)
2771 return 0;
2773 /* If this function has an entry in the dispatch table, we cannot
2774 omit it. */
2775 if (!dump_internal && !DECL_VINDEX (t)
2776 && *IDENTIFIER_POINTER (decl_name) == '_')
2778 if (IDENTIFIER_POINTER (decl_name)[1] == '_')
2779 return 0;
2781 INDENT (spc);
2782 pp_string (buffer, "-- skipped func ");
2783 pp_string (buffer, IDENTIFIER_POINTER (decl_name));
2784 return 1;
2787 if (need_indent)
2788 INDENT (spc);
2790 if (is_constructor)
2791 pp_string (buffer, "function New_");
2792 else if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
2794 is_function = false;
2795 pp_string (buffer, "procedure ");
2797 else
2798 pp_string (buffer, "function ");
2800 in_function = is_function;
2801 is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
2803 if (is_destructor)
2804 print_destructor (buffer, t);
2805 else
2806 dump_ada_decl_name (buffer, t, false);
2808 dump_ada_function_declaration
2809 (buffer, t, is_method, is_constructor, is_destructor, spc);
2810 in_function = prev_in_function;
2812 if (is_function)
2814 pp_string (buffer, " return ");
2816 if (is_constructor)
2818 dump_ada_decl_name (buffer, t, false);
2820 else
2822 dump_generic_ada_node
2823 (buffer, TREE_TYPE (TREE_TYPE (t)), type, cpp_check,
2824 spc, false, true);
2828 if (is_constructor && cpp_check && type
2829 && AGGREGATE_TYPE_P (type)
2830 && TYPE_METHODS (type))
2832 tree tmp = TYPE_METHODS (type);
2834 for (; tmp; tmp = TREE_CHAIN (tmp))
2835 if (cpp_check (tmp, IS_ABSTRACT))
2837 is_abstract_class = 1;
2838 break;
2842 if (is_abstract || is_abstract_class)
2843 pp_string (buffer, " is abstract");
2845 pp_semicolon (buffer);
2846 pp_string (buffer, " -- ");
2847 dump_sloc (buffer, t);
2849 if (is_abstract)
2850 return 1;
2852 newline_and_indent (buffer, spc);
2854 if (is_constructor)
2856 pp_string (buffer, "pragma CPP_Constructor (New_");
2857 dump_ada_decl_name (buffer, t, false);
2858 pp_string (buffer, ", \"");
2859 pp_asm_name (buffer, t);
2860 pp_string (buffer, "\");");
2862 else if (is_destructor)
2864 pp_string (buffer, "pragma Import (CPP, ");
2865 print_destructor (buffer, t);
2866 pp_string (buffer, ", \"");
2867 pp_asm_name (buffer, t);
2868 pp_string (buffer, "\");");
2870 else
2872 dump_ada_import (buffer, t);
2875 return 1;
2877 else if (TREE_CODE (t) == TYPE_DECL && !DECL_ORIGINAL_TYPE (t))
2879 int is_interface = 0;
2880 int is_abstract_record = 0;
2882 if (need_indent)
2883 INDENT (spc);
2885 /* Anonymous structs/unions */
2886 dump_generic_ada_node
2887 (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
2889 if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
2890 || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE)
2892 pp_string (buffer, " (discr : unsigned := 0)");
2895 pp_string (buffer, " is ");
2897 /* Check whether we have an Ada interface compatible class. */
2898 if (cpp_check && AGGREGATE_TYPE_P (TREE_TYPE (t))
2899 && TYPE_METHODS (TREE_TYPE (t)))
2901 int num_fields = 0;
2902 tree tmp = TYPE_FIELDS (TREE_TYPE (t));
2904 /* Check that there are no fields other than the virtual table. */
2905 for (; tmp; tmp = TREE_CHAIN (tmp))
2907 if (TREE_CODE (tmp) == TYPE_DECL)
2908 continue;
2909 num_fields++;
2912 if (num_fields == 1)
2913 is_interface = 1;
2915 /* Also check that there are only virtual methods. */
2916 for (tmp = TYPE_METHODS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
2918 if (cpp_check (tmp, IS_ABSTRACT))
2919 is_abstract_record = 1;
2920 else
2921 is_interface = 0;
2925 TREE_VISITED (t) = 1;
2926 if (is_interface)
2928 pp_string (buffer, "limited interface; -- ");
2929 dump_sloc (buffer, t);
2930 newline_and_indent (buffer, spc);
2931 pp_string (buffer, "pragma Import (CPP, ");
2932 dump_generic_ada_node
2933 (buffer, TYPE_NAME (TREE_TYPE (t)), type, cpp_check,
2934 spc, false, true);
2935 pp_character (buffer, ')');
2937 print_ada_methods (buffer, TREE_TYPE (t), cpp_check, spc);
2939 else
2941 if (is_abstract_record)
2942 pp_string (buffer, "abstract ");
2943 dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, false);
2946 else
2948 if (need_indent)
2949 INDENT (spc);
2951 if (TREE_CODE (t) == FIELD_DECL && DECL_NAME (t))
2952 check_name (buffer, t);
2954 /* Print variable/type's name. */
2955 dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, true);
2957 if (TREE_CODE (t) == TYPE_DECL)
2959 tree orig = DECL_ORIGINAL_TYPE (t);
2960 int is_subtype = orig && TYPE_NAME (orig) && orig != TREE_TYPE (t);
2962 if (!is_subtype
2963 && (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
2964 || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE))
2965 pp_string (buffer, " (discr : unsigned := 0)");
2967 pp_string (buffer, " is ");
2969 dump_generic_ada_node
2970 (buffer, orig, t, cpp_check, spc, false, is_subtype);
2972 else
2974 if (spc == INDENT_INCR || TREE_STATIC (t))
2975 is_var = 1;
2977 pp_string (buffer, " : ");
2979 /* Print type declaration. */
2981 if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
2982 && !TYPE_NAME (TREE_TYPE (t)))
2984 dump_ada_double_name (buffer, type, t, "_union");
2986 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
2988 if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
2989 pp_string (buffer, "aliased ");
2991 dump_generic_ada_node
2992 (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
2994 else
2996 if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
2997 && (TYPE_NAME (TREE_TYPE (t))
2998 || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE))
2999 pp_string (buffer, "aliased ");
3001 dump_generic_ada_node
3002 (buffer, TREE_TYPE (t), TREE_TYPE (t), cpp_check,
3003 spc, false, true);
3008 if (is_class)
3010 spc -= 3;
3011 newline_and_indent (buffer, spc);
3012 pp_string (buffer, "end;");
3013 newline_and_indent (buffer, spc);
3014 pp_string (buffer, "use Class_");
3015 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
3016 pp_semicolon (buffer);
3017 pp_newline (buffer);
3019 /* All needed indentation/newline performed already, so return 0. */
3020 return 0;
3022 else
3024 pp_string (buffer, "; -- ");
3025 dump_sloc (buffer, t);
3028 if (is_var)
3030 newline_and_indent (buffer, spc);
3031 dump_ada_import (buffer, t);
3034 return 1;
3037 /* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
3038 with Ada syntax. CPP_CHECK is used to perform C++ queries on nodes. SPC
3039 is the indentation level. If DISPLAY_CONVENTION is true, also print the
3040 pragma Convention for NODE. */
3042 static void
3043 print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
3044 int (*cpp_check)(tree, cpp_operation), int spc,
3045 bool display_convention)
3047 tree tmp;
3048 int is_union =
3049 TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
3050 char buf [16];
3051 int field_num = 0;
3052 int field_spc = spc + INDENT_INCR;
3053 int need_semicolon;
3055 bitfield_used = false;
3057 if (!TYPE_FIELDS (node))
3058 pp_string (buffer, "null record;");
3059 else
3061 pp_string (buffer, "record");
3063 /* Print the contents of the structure. */
3065 if (is_union)
3067 newline_and_indent (buffer, spc + INDENT_INCR);
3068 pp_string (buffer, "case discr is");
3069 field_spc = spc + INDENT_INCR * 3;
3072 pp_newline (buffer);
3074 /* Print the non-static fields of the structure. */
3075 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3077 /* Add parent field if needed. */
3078 if (!DECL_NAME (tmp))
3080 if (!is_tagged_type (TREE_TYPE (tmp)))
3082 if (!TYPE_NAME (TREE_TYPE (tmp)))
3083 print_ada_declaration
3084 (buffer, tmp, type, cpp_check, field_spc);
3085 else
3087 INDENT (field_spc);
3089 if (field_num == 0)
3090 pp_string (buffer, "parent : ");
3091 else
3093 sprintf (buf, "field_%d : ", field_num + 1);
3094 pp_string (buffer, buf);
3096 dump_ada_decl_name
3097 (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
3098 pp_semicolon (buffer);
3100 pp_newline (buffer);
3101 field_num++;
3104 /* Avoid printing the structure recursively. */
3105 else if ((TREE_TYPE (tmp) != node
3106 || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
3107 && TREE_TYPE (TREE_TYPE (tmp)) != node))
3108 && TREE_CODE (tmp) != TYPE_DECL
3109 && !TREE_STATIC (tmp))
3111 /* Skip internal virtual table field. */
3112 if (strncmp (IDENTIFIER_POINTER (DECL_NAME (tmp)), "_vptr", 5))
3114 if (is_union)
3116 if (TREE_CHAIN (tmp)
3117 && TREE_TYPE (TREE_CHAIN (tmp)) != node
3118 && TREE_CODE (TREE_CHAIN (tmp)) != TYPE_DECL)
3119 sprintf (buf, "when %d =>", field_num);
3120 else
3121 sprintf (buf, "when others =>");
3123 INDENT (spc + INDENT_INCR * 2);
3124 pp_string (buffer, buf);
3125 pp_newline (buffer);
3128 if (print_ada_declaration (buffer,
3129 tmp, type, cpp_check, field_spc))
3131 pp_newline (buffer);
3132 field_num++;
3138 if (is_union)
3140 INDENT (spc + INDENT_INCR);
3141 pp_string (buffer, "end case;");
3142 pp_newline (buffer);
3145 if (field_num == 0)
3147 INDENT (spc + INDENT_INCR);
3148 pp_string (buffer, "null;");
3149 pp_newline (buffer);
3152 INDENT (spc);
3153 pp_string (buffer, "end record;");
3156 newline_and_indent (buffer, spc);
3158 if (!display_convention)
3159 return;
3161 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
3163 if (TYPE_METHODS (TREE_TYPE (type)))
3164 pp_string (buffer, "pragma Import (CPP, ");
3165 else
3166 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
3168 else
3169 pp_string (buffer, "pragma Convention (C, ");
3171 package_prefix = false;
3172 dump_generic_ada_node
3173 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3174 package_prefix = true;
3175 pp_character (buffer, ')');
3177 if (is_union)
3179 pp_semicolon (buffer);
3180 newline_and_indent (buffer, spc);
3181 pp_string (buffer, "pragma Unchecked_Union (");
3183 dump_generic_ada_node
3184 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3185 pp_character (buffer, ')');
3188 if (bitfield_used)
3190 pp_semicolon (buffer);
3191 newline_and_indent (buffer, spc);
3192 pp_string (buffer, "pragma Pack (");
3193 dump_generic_ada_node
3194 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3195 pp_character (buffer, ')');
3196 bitfield_used = false;
3199 print_ada_methods (buffer, node, cpp_check, spc);
3201 /* Print the static fields of the structure, if any. */
3202 need_semicolon = TYPE_METHODS (node) == NULL_TREE;
3203 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3205 if (DECL_NAME (tmp) && TREE_STATIC (tmp))
3207 if (need_semicolon)
3209 need_semicolon = false;
3210 pp_semicolon (buffer);
3212 pp_newline (buffer);
3213 pp_newline (buffer);
3214 print_ada_declaration (buffer, tmp, type, cpp_check, spc);
3219 /* Dump all the declarations in SOURCE_FILE to an Ada spec.
3220 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3221 nodes for SOURCE_FILE. CPP_CHECK is used to perform C++ queries on
3222 nodes. */
3224 static void
3225 dump_ads (const char *source_file,
3226 void (*collect_all_refs)(const char *),
3227 int (*cpp_check)(tree, cpp_operation))
3229 char *ads_name;
3230 char *pkg_name;
3231 char *s;
3232 FILE *f;
3234 pkg_name = get_ada_package (source_file);
3236 /* Construct the .ads filename and package name. */
3237 ads_name = xstrdup (pkg_name);
3239 for (s = ads_name; *s; s++)
3240 *s = TOLOWER (*s);
3242 ads_name = reconcat (ads_name, ads_name, ".ads", NULL);
3244 /* Write out the .ads file. */
3245 f = fopen (ads_name, "w");
3246 if (f)
3248 pretty_printer pp;
3250 pp_construct (&pp, NULL, 0);
3251 pp_needs_newline (&pp) = true;
3252 pp.buffer->stream = f;
3254 /* Dump all relevant macros. */
3255 dump_ada_macros (&pp, source_file);
3257 /* Reset the table of withs for this file. */
3258 reset_ada_withs ();
3260 (*collect_all_refs) (source_file);
3262 /* Dump all references. */
3263 dump_ada_nodes (&pp, source_file, cpp_check);
3265 /* Dump withs. */
3266 dump_ada_withs (f);
3268 fprintf (f, "\npackage %s is\n\n", pkg_name);
3269 pp_write_text_to_stream (&pp);
3270 /* ??? need to free pp */
3271 fprintf (f, "end %s;\n", pkg_name);
3272 fclose (f);
3275 free (ads_name);
3276 free (pkg_name);
3279 static const char **source_refs = NULL;
3280 static int source_refs_used = 0;
3281 static int source_refs_allocd = 0;
3283 /* Add an entry for FILENAME to the table SOURCE_REFS. */
3285 void
3286 collect_source_ref (const char *filename)
3288 int i;
3290 if (!filename)
3291 return;
3293 if (source_refs_allocd == 0)
3295 source_refs_allocd = 1024;
3296 source_refs = XNEWVEC (const char *, source_refs_allocd);
3299 for (i = 0; i < source_refs_used; i++)
3300 if (filename == source_refs [i])
3301 return;
3303 if (source_refs_used == source_refs_allocd)
3305 source_refs_allocd *= 2;
3306 source_refs = XRESIZEVEC (const char *, source_refs, source_refs_allocd);
3309 source_refs [source_refs_used++] = filename;
3312 /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
3313 using callbacks COLLECT_ALL_REFS and CPP_CHECK.
3314 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3315 nodes for a given source file.
3316 CPP_CHECK is used to perform C++ queries on nodes, or NULL for the C
3317 front-end. */
3319 void
3320 dump_ada_specs (void (*collect_all_refs)(const char *),
3321 int (*cpp_check)(tree, cpp_operation))
3323 int i;
3325 /* Iterate over the list of files to dump specs for */
3326 for (i = 0; i < source_refs_used; i++)
3327 dump_ads (source_refs [i], collect_all_refs, cpp_check);
3329 /* Free files table. */
3330 free (source_refs);